From c999af71e72c88c8ddf04e728368b3ea1c46547c Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 3 Sep 2025 15:17:21 +0900 Subject: [PATCH 01/93] =?UTF-8?q?[chore]=20Firebase=20key=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index b10e200c4..e971d692c 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ build/ !**/src/test/**/build/ *.yml deploy.sh +serviceAccountKey.json ### STS ### .apt_generated From 033e028e752eafc59196fe7182dbe5d841f0c20f Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 3 Sep 2025 15:17:39 +0900 Subject: [PATCH 02/93] =?UTF-8?q?[chore]=20Firebase=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EC=A3=BC=EC=9E=85=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.gradle b/build.gradle index 388a4ff77..74aa09e47 100644 --- a/build.gradle +++ b/build.gradle @@ -89,6 +89,8 @@ dependencies { implementation "org.flywaydb:flyway-core" implementation "org.flywaydb:flyway-mysql" + // Firebase + implementation 'com.google.firebase:firebase-admin:9.3.0' } def querydslDir = layout.buildDirectory.dir("generated/querydsl").get().asFile From 21e114802880a0601206aa0b9bfc54f19c8de534 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 3 Sep 2025 15:18:10 +0900 Subject: [PATCH 03/93] =?UTF-8?q?[infra]=20cd=EC=97=90=20Firebase=20Key=20?= =?UTF-8?q?=EC=A3=BC=EC=9E=85=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/cd-workflow-dev.yml | 7 +++++++ .github/workflows/cd-workflow-prod.yml | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/.github/workflows/cd-workflow-dev.yml b/.github/workflows/cd-workflow-dev.yml index 4e26195bd..4d9ed0c4f 100644 --- a/.github/workflows/cd-workflow-dev.yml +++ b/.github/workflows/cd-workflow-dev.yml @@ -11,6 +11,7 @@ permissions: env: RESOURCE_PATH: src/main/resources COMPOSE_PATH: /home/ec2-user/compose + FIREBASE_KEY_PATH: src/main/resources/firebase APP_PORT: 8000 jobs: @@ -33,6 +34,12 @@ jobs: echo "${{ secrets.APPLICATION_YML_DEV }}" | base64 --decode > ${{ env.RESOURCE_PATH }}/application.yml shell: bash + - name: ๐Ÿ” Create Firebase Key from secret (base64) + run: | + mkdir -p ${{ env.FIREBASE_KEY_PATH }} + echo "${{ secrets.FIREBASE_KEY }}" | base64 --decode > ${{ env.FIREBASE_KEY_PATH }}/serviceAccountKey.json + shell: bash + - name: ๐Ÿ˜ Cache Gradle dependencies uses: actions/cache@v3 with: diff --git a/.github/workflows/cd-workflow-prod.yml b/.github/workflows/cd-workflow-prod.yml index 651aecdfa..203cea8f6 100644 --- a/.github/workflows/cd-workflow-prod.yml +++ b/.github/workflows/cd-workflow-prod.yml @@ -11,6 +11,7 @@ permissions: env: RESOURCE_PATH: src/main/resources COMPOSE_PATH: /home/ec2-user/compose + FIREBASE_KEY_PATH: src/main/resources/firebase APP_PORT: 8000 jobs: @@ -33,6 +34,12 @@ jobs: echo "${{ secrets.APPLICATION_YML_PROD }}" | base64 --decode > ${{ env.RESOURCE_PATH }}/application.yml shell: bash + - name: ๐Ÿ” Create Firebase Key from secret (base64) + run: | + mkdir -p ${{ env.FIREBASE_KEY_PATH }} + echo "${{ secrets.FIREBASE_KEY }}" | base64 --decode > ${{ env.FIREBASE_KEY_PATH }}/serviceAccountKey.json + shell: bash + - name: ๐Ÿ˜ Cache Gradle dependencies uses: actions/cache@v3 with: From 8550f95446c455e6aa18df21bd621080f2949dc9 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 3 Sep 2025 15:18:30 +0900 Subject: [PATCH 04/93] =?UTF-8?q?[chore]=20Async=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/konkuk/thip/ThipServerApplication.java | 2 -- src/main/java/konkuk/thip/config/AsyncConfig.java | 9 +++++++++ 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 src/main/java/konkuk/thip/config/AsyncConfig.java diff --git a/src/main/java/konkuk/thip/ThipServerApplication.java b/src/main/java/konkuk/thip/ThipServerApplication.java index 760455496..8a2d53b91 100644 --- a/src/main/java/konkuk/thip/ThipServerApplication.java +++ b/src/main/java/konkuk/thip/ThipServerApplication.java @@ -4,12 +4,10 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.ConfigurationPropertiesScan; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; -import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; @EnableJpaAuditing @EnableScheduling -@EnableAsync @ConfigurationPropertiesScan @SpringBootApplication public class ThipServerApplication { diff --git a/src/main/java/konkuk/thip/config/AsyncConfig.java b/src/main/java/konkuk/thip/config/AsyncConfig.java new file mode 100644 index 000000000..24247fa87 --- /dev/null +++ b/src/main/java/konkuk/thip/config/AsyncConfig.java @@ -0,0 +1,9 @@ +package konkuk.thip.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; + +@Configuration +@EnableAsync +public class AsyncConfig { +} From b855d4b74662c0d9c8725cee4485dba671ca8512 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 3 Sep 2025 15:18:46 +0900 Subject: [PATCH 05/93] =?UTF-8?q?[fix]=20SignatureException=20catch=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/konkuk/thip/common/security/util/JwtUtil.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/konkuk/thip/common/security/util/JwtUtil.java b/src/main/java/konkuk/thip/common/security/util/JwtUtil.java index 90024d7a2..9d0b91538 100644 --- a/src/main/java/konkuk/thip/common/security/util/JwtUtil.java +++ b/src/main/java/konkuk/thip/common/security/util/JwtUtil.java @@ -4,6 +4,7 @@ import io.jsonwebtoken.Jwts; import io.jsonwebtoken.MalformedJwtException; import io.jsonwebtoken.UnsupportedJwtException; +import io.jsonwebtoken.security.SignatureException; import konkuk.thip.common.security.oauth2.LoginUser; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -53,6 +54,8 @@ public boolean validateToken(String token) { try { Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token); return true; + } catch (SignatureException e) { + log.info("Invalid JWT Signature", e); } catch (MalformedJwtException e) { log.info("Invalid JWT Token", e); } catch (ExpiredJwtException e) { From ada09cd74ccc639fa0e7edc18ec58a942753e8bc Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 3 Sep 2025 15:20:17 +0900 Subject: [PATCH 06/93] =?UTF-8?q?[chore]=20Firebase=20=EC=B4=88=EA=B8=B0?= =?UTF-8?q?=ED=99=94=20=EC=84=A4=EC=A0=95=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../konkuk/thip/config/FirebaseConfig.java | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/main/java/konkuk/thip/config/FirebaseConfig.java diff --git a/src/main/java/konkuk/thip/config/FirebaseConfig.java b/src/main/java/konkuk/thip/config/FirebaseConfig.java new file mode 100644 index 000000000..473059f5d --- /dev/null +++ b/src/main/java/konkuk/thip/config/FirebaseConfig.java @@ -0,0 +1,43 @@ +package konkuk.thip.config; + +import com.google.auth.oauth2.GoogleCredentials; +import com.google.firebase.FirebaseApp; +import com.google.firebase.FirebaseOptions; +import com.google.firebase.auth.FirebaseAuth; +import com.google.firebase.messaging.FirebaseMessaging; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; + +import java.io.IOException; + +@Configuration +public class FirebaseConfig { + + @Bean + FirebaseMessaging firebaseMessaging(FirebaseApp firebaseApp) { + return FirebaseMessaging.getInstance(firebaseApp); + } + + @Bean + FirebaseApp firebaseApp(@Value("${firebase.file-path}") String filePath) throws IOException { + GoogleCredentials googleCredentials = GoogleCredentials + .fromStream(new ClassPathResource(filePath).getInputStream()); + + FirebaseOptions firebaseOptions = FirebaseOptions.builder() + .setCredentials(googleCredentials) + .build(); + + if (FirebaseApp.getApps().isEmpty()) { + return FirebaseApp.initializeApp(firebaseOptions); + } + + return FirebaseApp.getInstance(); + } + + @Bean + FirebaseAuth firebaseAuth(FirebaseApp firebaseApp) { + return FirebaseAuth.getInstance(firebaseApp); + } +} From feafca35fed8738142d3bd73c9507008f38c90a1 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 3 Sep 2025 15:20:31 +0900 Subject: [PATCH 07/93] =?UTF-8?q?[chore]=20Fcm=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EB=B8=94=20=EC=A0=95=EC=9D=98=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/out/jpa/FcmTokenJpaEntity.java | 51 ++++++++++++++++++ .../adapter/out/jpa/PlatformType.java | 5 ++ .../adapter/out/mapper/FcmTokenMapper.java | 36 +++++++++++++ .../thip/notification/domain/FcmToken.java | 53 +++++++++++++++++++ 4 files changed, 145 insertions(+) create mode 100644 src/main/java/konkuk/thip/notification/adapter/out/jpa/FcmTokenJpaEntity.java create mode 100644 src/main/java/konkuk/thip/notification/adapter/out/jpa/PlatformType.java create mode 100644 src/main/java/konkuk/thip/notification/adapter/out/mapper/FcmTokenMapper.java create mode 100644 src/main/java/konkuk/thip/notification/domain/FcmToken.java diff --git a/src/main/java/konkuk/thip/notification/adapter/out/jpa/FcmTokenJpaEntity.java b/src/main/java/konkuk/thip/notification/adapter/out/jpa/FcmTokenJpaEntity.java new file mode 100644 index 000000000..15871db8e --- /dev/null +++ b/src/main/java/konkuk/thip/notification/adapter/out/jpa/FcmTokenJpaEntity.java @@ -0,0 +1,51 @@ +package konkuk.thip.notification.adapter.out.jpa; + +import jakarta.persistence.*; +import konkuk.thip.common.entity.BaseJpaEntity; +import konkuk.thip.notification.domain.FcmToken; +import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; +import lombok.*; + +import java.time.LocalDate; + +@Entity +@Table(name = "fcm_tokens") +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Builder +public class FcmTokenJpaEntity extends BaseJpaEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long fcmTokenId; + + @Column(name = "fcm_token", nullable = false) + private String fcmToken; + + @Column(name = "device_id", length = 128, nullable = false, unique = true) + private String deviceId; + + @Enumerated(EnumType.STRING) + @Column(name = "platform", length = 16, nullable = false) + private PlatformType platformType; + + @Column(name = "last_used_time", nullable = false) + private LocalDate lastUsedTime; + + @Column(name = "is_enabled", nullable = false) + private boolean isEnabled; // ํ‘ธ์‰ฌ์•Œ๋ฆผ ์ˆ˜์‹  ์—ฌ๋ถ€ + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id", nullable = false) + private UserJpaEntity userJpaEntity; + + public void updateFrom(FcmToken fcmToken, UserJpaEntity userJpaEntity) { + this.fcmToken = fcmToken.getFcmToken(); + this.platformType = fcmToken.getPlatformType(); + this.lastUsedTime = fcmToken.getLastUsedTime(); + this.userJpaEntity = userJpaEntity; + + this.isEnabled = fcmToken.isEnabled(); + } +} diff --git a/src/main/java/konkuk/thip/notification/adapter/out/jpa/PlatformType.java b/src/main/java/konkuk/thip/notification/adapter/out/jpa/PlatformType.java new file mode 100644 index 000000000..303d5d246 --- /dev/null +++ b/src/main/java/konkuk/thip/notification/adapter/out/jpa/PlatformType.java @@ -0,0 +1,5 @@ +package konkuk.thip.notification.adapter.out.jpa; + +public enum PlatformType { + ANDROID, WEB +} diff --git a/src/main/java/konkuk/thip/notification/adapter/out/mapper/FcmTokenMapper.java b/src/main/java/konkuk/thip/notification/adapter/out/mapper/FcmTokenMapper.java new file mode 100644 index 000000000..1acb141bf --- /dev/null +++ b/src/main/java/konkuk/thip/notification/adapter/out/mapper/FcmTokenMapper.java @@ -0,0 +1,36 @@ +package konkuk.thip.notification.adapter.out.mapper; + +import konkuk.thip.notification.adapter.out.jpa.FcmTokenJpaEntity; +import konkuk.thip.notification.domain.FcmToken; +import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; +import org.springframework.stereotype.Component; + +@Component +public class FcmTokenMapper { + + public FcmTokenJpaEntity toJpaEntity(FcmToken fcmToken, UserJpaEntity userJpaEntity) { + return FcmTokenJpaEntity.builder() + .fcmToken(fcmToken.getFcmToken()) + .deviceId(fcmToken.getDeviceId()) + .platformType(fcmToken.getPlatformType()) + .lastUsedTime(fcmToken.getLastUsedTime()) + .isEnabled(fcmToken.isEnabled()) + .userJpaEntity(userJpaEntity) + .build(); + } + + public FcmToken toDomainEntity(FcmTokenJpaEntity fcmTokenJpaEntity) { + return FcmToken.builder() + .id(fcmTokenJpaEntity.getFcmTokenId()) + .fcmToken(fcmTokenJpaEntity.getFcmToken()) + .deviceId(fcmTokenJpaEntity.getDeviceId()) + .platformType(fcmTokenJpaEntity.getPlatformType()) + .lastUsedTime(fcmTokenJpaEntity.getLastUsedTime()) + .isEnabled(fcmTokenJpaEntity.isEnabled()) + .userId(fcmTokenJpaEntity.getUserJpaEntity().getUserId()) + .createdAt(fcmTokenJpaEntity.getCreatedAt()) + .modifiedAt(fcmTokenJpaEntity.getModifiedAt()) + .status(fcmTokenJpaEntity.getStatus()) + .build(); + } +} diff --git a/src/main/java/konkuk/thip/notification/domain/FcmToken.java b/src/main/java/konkuk/thip/notification/domain/FcmToken.java new file mode 100644 index 000000000..1b9900a82 --- /dev/null +++ b/src/main/java/konkuk/thip/notification/domain/FcmToken.java @@ -0,0 +1,53 @@ +package konkuk.thip.notification.domain; + +import konkuk.thip.common.entity.BaseDomainEntity; +import konkuk.thip.notification.adapter.out.jpa.PlatformType; +import lombok.Getter; +import lombok.experimental.SuperBuilder; + +import java.time.LocalDate; + +@Getter +@SuperBuilder +public class FcmToken extends BaseDomainEntity { + + private Long id; + + private String fcmToken; + + private String deviceId; + + private PlatformType platformType; + + private LocalDate lastUsedTime; + + private boolean isEnabled; // ํ‘ธ์‰ฌ์•Œ๋ฆผ ์ˆ˜์‹  ์—ฌ๋ถ€ + + private Long userId; + + public static FcmToken withoutId ( + String fcmToken, + String deviceId, + PlatformType platformType, + LocalDate lastUsedTime, + boolean isEnabled, + Long userId + ) { + return FcmToken.builder() + .fcmToken(fcmToken) + .deviceId(deviceId) + .platformType(platformType) + .lastUsedTime(lastUsedTime) + .isEnabled(isEnabled) + .userId(userId) + .build(); + } + + // ํ† ํฐ ๊ฐฑ์‹  + public void updateToken(String fcmToken, PlatformType platformType, LocalDate lastUsedTime, Long userId) { + this.fcmToken = fcmToken; + this.platformType = platformType; + this.lastUsedTime = lastUsedTime; + this.userId = userId; + } +} From 9a4fd418d17f026eb9e1b404aad320e74695bbae Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 3 Sep 2025 15:20:42 +0900 Subject: [PATCH 08/93] =?UTF-8?q?[chore]=20Fcm=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EA=B5=AC=ED=98=84=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../port/in/FcmRegisterUseCase.java | 7 +++ .../service/FcmRegisterService.java | 45 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 src/main/java/konkuk/thip/notification/application/port/in/FcmRegisterUseCase.java create mode 100644 src/main/java/konkuk/thip/notification/application/service/FcmRegisterService.java diff --git a/src/main/java/konkuk/thip/notification/application/port/in/FcmRegisterUseCase.java b/src/main/java/konkuk/thip/notification/application/port/in/FcmRegisterUseCase.java new file mode 100644 index 000000000..ff9b096ed --- /dev/null +++ b/src/main/java/konkuk/thip/notification/application/port/in/FcmRegisterUseCase.java @@ -0,0 +1,7 @@ +package konkuk.thip.notification.application.port.in; + +import konkuk.thip.notification.application.port.in.dto.FcmTokenRegisterCommand; + +public interface FcmRegisterUseCase { + void registerToken(FcmTokenRegisterCommand command); +} diff --git a/src/main/java/konkuk/thip/notification/application/service/FcmRegisterService.java b/src/main/java/konkuk/thip/notification/application/service/FcmRegisterService.java new file mode 100644 index 000000000..679042bae --- /dev/null +++ b/src/main/java/konkuk/thip/notification/application/service/FcmRegisterService.java @@ -0,0 +1,45 @@ +package konkuk.thip.notification.application.service; + +import konkuk.thip.notification.application.port.in.FcmRegisterUseCase; +import konkuk.thip.notification.application.port.in.dto.FcmTokenRegisterCommand; +import konkuk.thip.notification.application.port.out.FcmTokenLoadPort; +import konkuk.thip.notification.domain.FcmToken; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.time.LocalDate; + +@Service +@RequiredArgsConstructor +public class FcmRegisterService implements FcmRegisterUseCase { + + private final FcmTokenLoadPort fcmTokenLoadPort; + + @Override + public void registerToken(FcmTokenRegisterCommand command) { + // ๊ฐ™์€ ๋””๋ฐ”์ด์Šค๋กœ ๋“ฑ๋ก๋œ ํ† ํฐ์ด ์žˆ๋Š”์ง€ ํ™•์ธ + fcmTokenLoadPort.findByDeviceId(command.deviceId()).ifPresentOrElse( + existingToken -> { + // ์žˆ์œผ๋ฉด ์ƒˆ๋กœ์šด ๊ณ„์ •์œผ๋กœ ๊ต์ฒด ๋˜๋Š” ๊ธฐ์กด ๊ณ„์ •์˜ ํ† ํฐ ๊ฐฑ์‹  + existingToken.updateToken( + command.fcmToken(), + command.platformType(), + LocalDate.now(), + command.userId() + ); + fcmTokenLoadPort.update(existingToken); + }, + () -> { + // ์—†์œผ๋ฉด ์ƒˆ๋กœ ๋“ฑ๋ก + fcmTokenLoadPort.save(FcmToken.withoutId( + command.fcmToken(), + command.deviceId(), + command.platformType(), + LocalDate.now(), + true, + command.userId() + )); + } + ); + } +} From d91a428357b541f45b18254841204edd4dcd210a Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 3 Sep 2025 15:21:09 +0900 Subject: [PATCH 09/93] =?UTF-8?q?[feat]=20Fcm=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20=EA=B4=80=EB=A0=A8=20dto=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../in/web/request/FcmTokenRequest.java | 26 +++++++++++++++++++ .../port/in/dto/FcmTokenRegisterCommand.java | 13 ++++++++++ 2 files changed, 39 insertions(+) create mode 100644 src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenRequest.java create mode 100644 src/main/java/konkuk/thip/notification/application/port/in/dto/FcmTokenRegisterCommand.java diff --git a/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenRequest.java b/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenRequest.java new file mode 100644 index 000000000..86c65bbad --- /dev/null +++ b/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenRequest.java @@ -0,0 +1,26 @@ +package konkuk.thip.notification.adapter.in.web.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import konkuk.thip.notification.adapter.out.jpa.PlatformType; +import konkuk.thip.notification.application.port.in.dto.FcmTokenRegisterCommand; + +@Schema(description = "FCM ํ† ํฐ ๋“ฑ๋ก ์š”์ฒญ DTO") +public record FcmTokenRequest( + @Schema(description = "๋””๋ฐ”์ด์Šค ๊ณ ์œ  ID", example = "device12345") + String deviceId, + + @Schema(description = "FCM ํ† ํฐ", example = "fcm_token_example_123456") + String fcmToken, + + @Schema(description = "ํ”Œ๋žซํผ ํƒ€์ž… (ANDROID ๋˜๋Š” WEB)", example = "ANDROID") + PlatformType platformType +) { + public static FcmTokenRegisterCommand toCommand(FcmTokenRequest request, Long userId) { + return FcmTokenRegisterCommand.builder() + .deviceId(request.deviceId) + .fcmToken(request.fcmToken) + .platformType(request.platformType) + .userId(userId) + .build(); + } +} diff --git a/src/main/java/konkuk/thip/notification/application/port/in/dto/FcmTokenRegisterCommand.java b/src/main/java/konkuk/thip/notification/application/port/in/dto/FcmTokenRegisterCommand.java new file mode 100644 index 000000000..bc0b3738e --- /dev/null +++ b/src/main/java/konkuk/thip/notification/application/port/in/dto/FcmTokenRegisterCommand.java @@ -0,0 +1,13 @@ +package konkuk.thip.notification.application.port.in.dto; + +import konkuk.thip.notification.adapter.out.jpa.PlatformType; +import lombok.Builder; + +@Builder +public record FcmTokenRegisterCommand( + String deviceId, + String fcmToken, + PlatformType platformType, + Long userId +) { +} From 9d5b3f51294fda3a1cb78d6fa492c1103257f1b4 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 3 Sep 2025 15:21:15 +0900 Subject: [PATCH 10/93] =?UTF-8?q?[feat]=20Fcm=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EB=93=B1=EB=A1=9D=20api=20=ED=95=B8=EB=93=A4=EB=9F=AC=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../in/web/NotificationCommandController.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java b/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java index e27c11f9b..433106db6 100644 --- a/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java +++ b/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java @@ -1,10 +1,46 @@ package konkuk.thip.notification.adapter.in.web; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import konkuk.thip.common.dto.BaseResponse; +import konkuk.thip.common.security.annotation.UserId; +import konkuk.thip.notification.adapter.in.web.request.FcmTokenRequest; +import konkuk.thip.notification.application.port.in.FcmEnableStateChangeUseCase; +import konkuk.thip.notification.application.port.in.FcmRegisterUseCase; +import konkuk.thip.notification.adapter.in.web.request.FcmTokenEnableStateChangeRequest; import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; +@Tag(name = "Notification Command API", description = "์•Œ๋ฆผ ๊ด€๋ จ ์ƒํƒœ๋ณ€๊ฒฝ API") @RestController @RequiredArgsConstructor public class NotificationCommandController { + private final FcmRegisterUseCase fcmRegisterUseCase; + private final FcmEnableStateChangeUseCase fcmEnableStateChangeUseCase; + + @Operation(summary = "FCM ํ† ํฐ ๋“ฑ๋ก", description = "์‚ฌ์šฉ์ž์˜ FCM ํ† ํฐ์„ ์„œ๋ฒ„์— ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด ํ† ํฐ์ด ์žˆ๋‹ค๋ฉด userId+deviceId ๊ธฐ์ค€์œผ๋กœ ํ† ํฐ์„ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค.") + @PostMapping("/fcm-tokens") + public BaseResponse registerFcmToken( + @RequestBody @Valid FcmTokenRequest request, + @Parameter(hidden = true) @UserId Long userId + ) { + fcmRegisterUseCase.registerToken(FcmTokenRequest.toCommand(request, userId)); + return BaseResponse.ok(null); + } + + @Operation(summary = "ํ‘ธ์‹œ ์•Œ๋ฆผ ์„ค์ • ๋ณ€๊ฒฝ", description = "์‚ฌ์šฉ์ž์˜ ํ‘ธ์‹œ ์•Œ๋ฆผ ์ˆ˜์‹  ์—ฌ๋ถ€๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.") + @PatchMapping("/notifications/push") + public BaseResponse updatePushNotificationSetting( + @RequestBody FcmTokenEnableStateChangeRequest request, + @Parameter(hidden = true) @UserId Long userId + ) { + fcmEnableStateChangeUseCase.changeEnableState(); + return BaseResponse.ok(null); + } } From 3455198c2329ec5bccf2601c015a6c3f53830d5f Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 3 Sep 2025 15:21:29 +0900 Subject: [PATCH 11/93] =?UTF-8?q?[feat]=20Fcm=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=ED=95=84=EC=9A=94=ED=95=9C=20=EC=BF=BC?= =?UTF-8?q?=EB=A6=AC=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FcmTokenLoadPersistenceAdapter.java | 75 +++++++++++++++++++ .../repository/FcmTokenJpaRepository.java | 19 +++++ .../port/out/FcmTokenLoadPort.java | 18 +++++ 3 files changed, 112 insertions(+) create mode 100644 src/main/java/konkuk/thip/notification/adapter/out/persistence/FcmTokenLoadPersistenceAdapter.java create mode 100644 src/main/java/konkuk/thip/notification/adapter/out/persistence/repository/FcmTokenJpaRepository.java create mode 100644 src/main/java/konkuk/thip/notification/application/port/out/FcmTokenLoadPort.java diff --git a/src/main/java/konkuk/thip/notification/adapter/out/persistence/FcmTokenLoadPersistenceAdapter.java b/src/main/java/konkuk/thip/notification/adapter/out/persistence/FcmTokenLoadPersistenceAdapter.java new file mode 100644 index 000000000..d7548e781 --- /dev/null +++ b/src/main/java/konkuk/thip/notification/adapter/out/persistence/FcmTokenLoadPersistenceAdapter.java @@ -0,0 +1,75 @@ +package konkuk.thip.notification.adapter.out.persistence; + +import konkuk.thip.common.exception.EntityNotFoundException; +import konkuk.thip.common.exception.code.ErrorCode; +import konkuk.thip.notification.adapter.out.jpa.FcmTokenJpaEntity; +import konkuk.thip.notification.adapter.out.mapper.FcmTokenMapper; +import konkuk.thip.notification.adapter.out.persistence.repository.FcmTokenJpaRepository; +import konkuk.thip.notification.application.port.out.FcmTokenLoadPort; +import konkuk.thip.notification.domain.FcmToken; +import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; +import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Optional; + +@Repository +@RequiredArgsConstructor +public class FcmTokenLoadPersistenceAdapter implements FcmTokenLoadPort { + + private final FcmTokenJpaRepository fcmTokenJpaRepository; + private final UserJpaRepository userJpaRepository; + + private final FcmTokenMapper fcmTokenMapper; + + @Override + public Optional findByDeviceId(String deviceId) { + return fcmTokenJpaRepository.findByDeviceId(deviceId) + .map(fcmTokenMapper::toDomainEntity); + } + + @Override + public FcmToken save(FcmToken token) { + UserJpaEntity user = userJpaRepository.findById(token.getUserId()) + .orElseThrow(() -> new EntityNotFoundException(ErrorCode.USER_NOT_FOUND)); + + var saved = fcmTokenJpaRepository.save(fcmTokenMapper.toJpaEntity(token, user)); + return fcmTokenMapper.toDomainEntity(saved); + } + + @Override + public void update(FcmToken fcmToken) { + UserJpaEntity userJpaEntity = userJpaRepository.findById(fcmToken.getUserId()) + .orElseThrow(() -> new EntityNotFoundException(ErrorCode.USER_NOT_FOUND)); + + FcmTokenJpaEntity fcmTokenJpaEntity = fcmTokenJpaRepository.findByFcmTokenId(fcmToken.getId()) + .orElseThrow(() -> new EntityNotFoundException(ErrorCode.FCM_TOKEN_NOT_FOUND)); + + fcmTokenJpaEntity.updateFrom(fcmToken, userJpaEntity); + fcmTokenJpaRepository.save(fcmTokenJpaEntity); + } + + @Override + public List findEnabledByUserId(Long userId) { + return fcmTokenJpaRepository.findByUserIdAndIsEnabledTrue(userId).stream() + .map(fcmTokenMapper::toDomainEntity).toList(); + } + + @Override + public void disableById(Long id, String reason) { + var entity = fcmTokenJpaRepository.findById(id).orElse(null); + if (entity == null) return; + var disabled = FcmTokenJpaEntity.builder() + .fcmTokenId(entity.getFcmTokenId()) + .fcmToken(entity.getFcmToken()) + .deviceId(entity.getDeviceId()) + .platformType(entity.getPlatformType()) + .lastUsedTime(entity.getLastUsedTime()) + .isEnabled(false) + .userJpaEntity(entity.getUserJpaEntity()) + .build(); + fcmTokenJpaRepository.save(disabled); + } +} diff --git a/src/main/java/konkuk/thip/notification/adapter/out/persistence/repository/FcmTokenJpaRepository.java b/src/main/java/konkuk/thip/notification/adapter/out/persistence/repository/FcmTokenJpaRepository.java new file mode 100644 index 000000000..e58594525 --- /dev/null +++ b/src/main/java/konkuk/thip/notification/adapter/out/persistence/repository/FcmTokenJpaRepository.java @@ -0,0 +1,19 @@ +package konkuk.thip.notification.adapter.out.persistence.repository; + +import konkuk.thip.notification.adapter.out.jpa.FcmTokenJpaEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.List; +import java.util.Optional; + +public interface FcmTokenJpaRepository extends JpaRepository { + + @Query("SELECT f FROM FcmTokenJpaEntity f WHERE f.deviceId = :deviceId") + Optional findByDeviceId(String deviceId); + + @Query("SELECT f FROM FcmTokenJpaEntity f WHERE f.userJpaEntity.userId = :userId AND f.isEnabled = true") + List findByUserIdAndIsEnabledTrue(Long userId); + + Optional findByFcmTokenId(Long id); +} diff --git a/src/main/java/konkuk/thip/notification/application/port/out/FcmTokenLoadPort.java b/src/main/java/konkuk/thip/notification/application/port/out/FcmTokenLoadPort.java new file mode 100644 index 000000000..18d81a7ba --- /dev/null +++ b/src/main/java/konkuk/thip/notification/application/port/out/FcmTokenLoadPort.java @@ -0,0 +1,18 @@ +package konkuk.thip.notification.application.port.out; + +import konkuk.thip.notification.domain.FcmToken; + +import java.util.List; +import java.util.Optional; + +public interface FcmTokenLoadPort { + Optional findByDeviceId(String deviceId); + + FcmToken save(FcmToken token); + + void update(FcmToken fcmToken); + + List findEnabledByUserId(Long userId); + + void disableById(Long id, String reason); +} From 6c732587c05917a2745475afcf10958ef35fd9dc Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 3 Sep 2025 15:21:55 +0900 Subject: [PATCH 12/93] =?UTF-8?q?[feat]=20=ED=91=B8=EC=89=AC=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EC=97=AC=EB=B6=80=20=ED=99=9C=EC=84=B1/=EB=B9=84?= =?UTF-8?q?=ED=99=9C=EC=84=B1=ED=99=94=20=EC=84=A4=EC=A0=95=20api=20dto=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../request/FcmTokenEnableStateChangeRequest.java | 13 +++++++++++++ .../port/in/FcmEnableStateChangeUseCase.java | 7 +++++++ .../port/in/dto/FcmEnableStateChangeCommand.java | 8 ++++++++ 3 files changed, 28 insertions(+) create mode 100644 src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenEnableStateChangeRequest.java create mode 100644 src/main/java/konkuk/thip/notification/application/port/in/FcmEnableStateChangeUseCase.java create mode 100644 src/main/java/konkuk/thip/notification/application/port/in/dto/FcmEnableStateChangeCommand.java diff --git a/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenEnableStateChangeRequest.java b/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenEnableStateChangeRequest.java new file mode 100644 index 000000000..fe0f5ab02 --- /dev/null +++ b/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenEnableStateChangeRequest.java @@ -0,0 +1,13 @@ +package konkuk.thip.notification.adapter.in.web.request; + +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema(description = "ํ‘ธ์‹œ ์•Œ๋ฆผ ์„ค์ • ๋ณ€๊ฒฝ ์š”์ฒญ DTO") +public record FcmTokenEnableStateChangeRequest( + @Schema(description = "ํ‘ธ์‹œ ์•Œ๋ฆผ ์ˆ˜์‹  ์—ฌ๋ถ€", example = "true") + boolean isEnable, + + @Schema(description = "๋””๋ฐ”์ด์Šค ๊ณ ์œ  ID", example = "device12345") + String deviceId +) { +} diff --git a/src/main/java/konkuk/thip/notification/application/port/in/FcmEnableStateChangeUseCase.java b/src/main/java/konkuk/thip/notification/application/port/in/FcmEnableStateChangeUseCase.java new file mode 100644 index 000000000..3870c4bee --- /dev/null +++ b/src/main/java/konkuk/thip/notification/application/port/in/FcmEnableStateChangeUseCase.java @@ -0,0 +1,7 @@ +package konkuk.thip.notification.application.port.in; + +import konkuk.thip.notification.application.port.in.dto.FcmEnableStateChangeCommand; + +public interface FcmEnableStateChangeUseCase { + void changeEnableState(FcmEnableStateChangeCommand command); +} diff --git a/src/main/java/konkuk/thip/notification/application/port/in/dto/FcmEnableStateChangeCommand.java b/src/main/java/konkuk/thip/notification/application/port/in/dto/FcmEnableStateChangeCommand.java new file mode 100644 index 000000000..dd5942b07 --- /dev/null +++ b/src/main/java/konkuk/thip/notification/application/port/in/dto/FcmEnableStateChangeCommand.java @@ -0,0 +1,8 @@ +package konkuk.thip.notification.application.port.in.dto; + +public record FcmEnableStateChangeCommand( + Long userId, + boolean enable, + String deviceId +) { +} From 5b8764f350a2d154692cc735484995ea6d48e308 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 3 Sep 2025 15:46:07 +0900 Subject: [PATCH 13/93] =?UTF-8?q?[feat]=20=ED=91=B8=EC=89=AC=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EC=97=AC=EB=B6=80=20=ED=99=9C=EC=84=B1/=EB=B9=84?= =?UTF-8?q?=ED=99=9C=EC=84=B1=ED=99=94=20=EC=84=A4=EC=A0=95=20api=20?= =?UTF-8?q?=EC=84=9C=EB=B9=84=EC=8A=A4=20=EA=B5=AC=ED=98=84=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../port/in/FcmEnableStateChangeUseCase.java | 2 +- .../application/service/FcmRegisterService.java | 2 ++ .../konkuk/thip/notification/domain/FcmToken.java | 14 ++++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/main/java/konkuk/thip/notification/application/port/in/FcmEnableStateChangeUseCase.java b/src/main/java/konkuk/thip/notification/application/port/in/FcmEnableStateChangeUseCase.java index 3870c4bee..14ba4c395 100644 --- a/src/main/java/konkuk/thip/notification/application/port/in/FcmEnableStateChangeUseCase.java +++ b/src/main/java/konkuk/thip/notification/application/port/in/FcmEnableStateChangeUseCase.java @@ -3,5 +3,5 @@ import konkuk.thip.notification.application.port.in.dto.FcmEnableStateChangeCommand; public interface FcmEnableStateChangeUseCase { - void changeEnableState(FcmEnableStateChangeCommand command); + boolean changeEnableState(FcmEnableStateChangeCommand command); } diff --git a/src/main/java/konkuk/thip/notification/application/service/FcmRegisterService.java b/src/main/java/konkuk/thip/notification/application/service/FcmRegisterService.java index 679042bae..f64dd14b7 100644 --- a/src/main/java/konkuk/thip/notification/application/service/FcmRegisterService.java +++ b/src/main/java/konkuk/thip/notification/application/service/FcmRegisterService.java @@ -6,6 +6,7 @@ import konkuk.thip.notification.domain.FcmToken; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.time.LocalDate; @@ -16,6 +17,7 @@ public class FcmRegisterService implements FcmRegisterUseCase { private final FcmTokenLoadPort fcmTokenLoadPort; @Override + @Transactional public void registerToken(FcmTokenRegisterCommand command) { // ๊ฐ™์€ ๋””๋ฐ”์ด์Šค๋กœ ๋“ฑ๋ก๋œ ํ† ํฐ์ด ์žˆ๋Š”์ง€ ํ™•์ธ fcmTokenLoadPort.findByDeviceId(command.deviceId()).ifPresentOrElse( diff --git a/src/main/java/konkuk/thip/notification/domain/FcmToken.java b/src/main/java/konkuk/thip/notification/domain/FcmToken.java index 1b9900a82..a7e1b91e6 100644 --- a/src/main/java/konkuk/thip/notification/domain/FcmToken.java +++ b/src/main/java/konkuk/thip/notification/domain/FcmToken.java @@ -1,6 +1,8 @@ package konkuk.thip.notification.domain; import konkuk.thip.common.entity.BaseDomainEntity; +import konkuk.thip.common.exception.InvalidStateException; +import konkuk.thip.common.exception.code.ErrorCode; import konkuk.thip.notification.adapter.out.jpa.PlatformType; import lombok.Getter; import lombok.experimental.SuperBuilder; @@ -50,4 +52,16 @@ public void updateToken(String fcmToken, PlatformType platformType, LocalDate la this.lastUsedTime = lastUsedTime; this.userId = userId; } + + public void changeEnableState(boolean enable) { + validateChangeEnableState(enable); + this.isEnabled = enable; + } + + private void validateChangeEnableState(boolean enable) { + if (this.isEnabled == enable) { + throw new InvalidStateException(ErrorCode.FCM_TOKEN_ENABLED_STATE_ALREADY, + new IllegalArgumentException("์ด๋ฏธ " + (enable ? "ํ™œ์„ฑํ™”" : "๋น„ํ™œ์„ฑํ™”") + "๋œ ์ƒํƒœ์ž…๋‹ˆ๋‹ค.")); + } + } } From f93a277d54c818e2a55634d00e1de37b5985f618 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 3 Sep 2025 15:46:17 +0900 Subject: [PATCH 14/93] =?UTF-8?q?[feat]=20=ED=91=B8=EC=89=AC=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EC=97=AC=EB=B6=80=20=ED=99=9C=EC=84=B1/=EB=B9=84?= =?UTF-8?q?=ED=99=9C=EC=84=B1=ED=99=94=20=EC=84=A4=EC=A0=95=20api=20?= =?UTF-8?q?=EC=84=9C=EB=B9=84=EC=8A=A4=20=EA=B5=AC=ED=98=84=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/FcmEnableStateChangeService.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/main/java/konkuk/thip/notification/application/service/FcmEnableStateChangeService.java diff --git a/src/main/java/konkuk/thip/notification/application/service/FcmEnableStateChangeService.java b/src/main/java/konkuk/thip/notification/application/service/FcmEnableStateChangeService.java new file mode 100644 index 000000000..a300073db --- /dev/null +++ b/src/main/java/konkuk/thip/notification/application/service/FcmEnableStateChangeService.java @@ -0,0 +1,27 @@ +package konkuk.thip.notification.application.service; + +import konkuk.thip.notification.application.port.in.FcmEnableStateChangeUseCase; +import konkuk.thip.notification.application.port.in.dto.FcmEnableStateChangeCommand; +import konkuk.thip.notification.application.port.out.FcmTokenLoadPort; +import konkuk.thip.notification.domain.FcmToken; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class FcmEnableStateChangeService implements FcmEnableStateChangeUseCase { + + private final FcmTokenLoadPort fcmTokenLoadPort; + + @Override + @Transactional + public boolean changeEnableState(FcmEnableStateChangeCommand command) { + FcmToken fcmToken = fcmTokenLoadPort.getByDeviceIdOrThrow(command.deviceId()); + + fcmToken.changeEnableState(command.enable()); + fcmTokenLoadPort.update(fcmToken); + + return command.enable(); + } +} From 20f1d7878f8fc52689ed1161530b372a9c898986 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 3 Sep 2025 15:46:42 +0900 Subject: [PATCH 15/93] =?UTF-8?q?[feat]=20FCM=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20api=20=ED=95=B8=EB=93=A4=EB=9F=AC=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../in/web/NotificationCommandController.java | 38 +++++++++++++------ 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java b/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java index 433106db6..8121bd0be 100644 --- a/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java +++ b/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java @@ -6,15 +6,18 @@ import jakarta.validation.Valid; import konkuk.thip.common.dto.BaseResponse; import konkuk.thip.common.security.annotation.UserId; -import konkuk.thip.notification.adapter.in.web.request.FcmTokenRequest; +import konkuk.thip.common.swagger.annotation.ExceptionDescription; +import konkuk.thip.notification.adapter.in.web.request.FcmTokenDeleteRequest; +import konkuk.thip.notification.adapter.in.web.request.FcmTokenRegisterRequest; +import konkuk.thip.notification.adapter.in.web.response.FcmTokenEnableStateChangeResponse; import konkuk.thip.notification.application.port.in.FcmEnableStateChangeUseCase; import konkuk.thip.notification.application.port.in.FcmRegisterUseCase; import konkuk.thip.notification.adapter.in.web.request.FcmTokenEnableStateChangeRequest; +import konkuk.thip.notification.application.port.in.FcmDeleteUseCase; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.PatchMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; + +import static konkuk.thip.common.swagger.SwaggerResponseDescription.*; @Tag(name = "Notification Command API", description = "์•Œ๋ฆผ ๊ด€๋ จ ์ƒํƒœ๋ณ€๊ฒฝ API") @RestController @@ -23,24 +26,37 @@ public class NotificationCommandController { private final FcmRegisterUseCase fcmRegisterUseCase; private final FcmEnableStateChangeUseCase fcmEnableStateChangeUseCase; + private final FcmDeleteUseCase fcmDeleteUseCase; @Operation(summary = "FCM ํ† ํฐ ๋“ฑ๋ก", description = "์‚ฌ์šฉ์ž์˜ FCM ํ† ํฐ์„ ์„œ๋ฒ„์— ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด ํ† ํฐ์ด ์žˆ๋‹ค๋ฉด userId+deviceId ๊ธฐ์ค€์œผ๋กœ ํ† ํฐ์„ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค.") @PostMapping("/fcm-tokens") + @ExceptionDescription(FCM_TOKEN_REGISTER) public BaseResponse registerFcmToken( - @RequestBody @Valid FcmTokenRequest request, + @RequestBody @Valid FcmTokenRegisterRequest request, @Parameter(hidden = true) @UserId Long userId ) { - fcmRegisterUseCase.registerToken(FcmTokenRequest.toCommand(request, userId)); + fcmRegisterUseCase.registerToken(request.toCommand(userId)); return BaseResponse.ok(null); } - @Operation(summary = "ํ‘ธ์‹œ ์•Œ๋ฆผ ์„ค์ • ๋ณ€๊ฒฝ", description = "์‚ฌ์šฉ์ž์˜ ํ‘ธ์‹œ ์•Œ๋ฆผ ์ˆ˜์‹  ์—ฌ๋ถ€๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.") - @PatchMapping("/notifications/push") - public BaseResponse updatePushNotificationSetting( + @Operation(summary = "ํ‘ธ์‹œ ์•Œ๋ฆผ ์ˆ˜์‹  ์—ฌ๋ถ€ ์„ค์ • ๋ณ€๊ฒฝ", description = "์‚ฌ์šฉ์ž์˜ ํ‘ธ์‹œ ์•Œ๋ฆผ ์ˆ˜์‹  ์—ฌ๋ถ€๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.") + @ExceptionDescription(FCM_TOKEN_ENABLE_STATE_CHANGE) + @PatchMapping("/notifications/enable-state") + public BaseResponse updatePushNotificationSetting( @RequestBody FcmTokenEnableStateChangeRequest request, @Parameter(hidden = true) @UserId Long userId ) { - fcmEnableStateChangeUseCase.changeEnableState(); + return BaseResponse.ok( + FcmTokenEnableStateChangeResponse.of(fcmEnableStateChangeUseCase.changeEnableState(request.toCommand(userId)))); + } + + @DeleteMapping("/fcm-tokens") + @Operation(summary = "FCM ํ† ํฐ ์‚ญ์ œ", description = "์‚ฌ์šฉ์ž์˜ FCM ํ† ํฐ์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.") + public BaseResponse deleteFcmToken( + @RequestBody FcmTokenDeleteRequest request, + @Parameter(hidden = true) @UserId Long userId + ) { + fcmDeleteUseCase.deleteToken(request.toCommand(userId)); return BaseResponse.ok(null); } } From 0c462177c68ebafd66ea2c4423288bd81ae64ca7 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 3 Sep 2025 15:46:52 +0900 Subject: [PATCH 16/93] =?UTF-8?q?[feat]=20FCM=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20dto=20=EC=A0=95=EC=9D=98=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../in/web/request/FcmTokenDeleteRequest.java | 14 ++++++++++++++ .../adapter/in/web/request/UserSignupRequest.java | 7 ------- .../port/in/dto/FcmTokenDeleteCommand.java | 7 +++++++ 3 files changed, 21 insertions(+), 7 deletions(-) create mode 100644 src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenDeleteRequest.java delete mode 100644 src/main/java/konkuk/thip/notification/adapter/in/web/request/UserSignupRequest.java create mode 100644 src/main/java/konkuk/thip/notification/application/port/in/dto/FcmTokenDeleteCommand.java diff --git a/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenDeleteRequest.java b/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenDeleteRequest.java new file mode 100644 index 000000000..12caae20d --- /dev/null +++ b/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenDeleteRequest.java @@ -0,0 +1,14 @@ +package konkuk.thip.notification.adapter.in.web.request; + +import konkuk.thip.notification.application.port.in.dto.FcmTokenDeleteCommand; + +public record FcmTokenDeleteRequest( + String deviceId +) { + public FcmTokenDeleteCommand toCommand(Long userId) { + return new FcmTokenDeleteCommand( + userId, + this.deviceId + ); + } +} diff --git a/src/main/java/konkuk/thip/notification/adapter/in/web/request/UserSignupRequest.java b/src/main/java/konkuk/thip/notification/adapter/in/web/request/UserSignupRequest.java deleted file mode 100644 index d463dff6b..000000000 --- a/src/main/java/konkuk/thip/notification/adapter/in/web/request/UserSignupRequest.java +++ /dev/null @@ -1,7 +0,0 @@ -package konkuk.thip.notification.adapter.in.web.request; - -import lombok.Getter; - -@Getter -public class UserSignupRequest { -} diff --git a/src/main/java/konkuk/thip/notification/application/port/in/dto/FcmTokenDeleteCommand.java b/src/main/java/konkuk/thip/notification/application/port/in/dto/FcmTokenDeleteCommand.java new file mode 100644 index 000000000..4c977031e --- /dev/null +++ b/src/main/java/konkuk/thip/notification/application/port/in/dto/FcmTokenDeleteCommand.java @@ -0,0 +1,7 @@ +package konkuk.thip.notification.application.port.in.dto; + +public record FcmTokenDeleteCommand( + Long userId, + String deviceId +) { +} From 75df1f34fd221ac166224ef2e21da3a6a0cfeb90 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 3 Sep 2025 15:46:59 +0900 Subject: [PATCH 17/93] =?UTF-8?q?[feat]=20FCM=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EA=B5=AC=ED=98=84=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/port/in/FcmDeleteUseCase.java | 7 ++++++ .../application/service/FcmDeleteService.java | 22 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 src/main/java/konkuk/thip/notification/application/port/in/FcmDeleteUseCase.java create mode 100644 src/main/java/konkuk/thip/notification/application/service/FcmDeleteService.java diff --git a/src/main/java/konkuk/thip/notification/application/port/in/FcmDeleteUseCase.java b/src/main/java/konkuk/thip/notification/application/port/in/FcmDeleteUseCase.java new file mode 100644 index 000000000..b6335003b --- /dev/null +++ b/src/main/java/konkuk/thip/notification/application/port/in/FcmDeleteUseCase.java @@ -0,0 +1,7 @@ +package konkuk.thip.notification.application.port.in; + +import konkuk.thip.notification.application.port.in.dto.FcmTokenDeleteCommand; + +public interface FcmDeleteUseCase { + void deleteToken(FcmTokenDeleteCommand command); +} diff --git a/src/main/java/konkuk/thip/notification/application/service/FcmDeleteService.java b/src/main/java/konkuk/thip/notification/application/service/FcmDeleteService.java new file mode 100644 index 000000000..4a01f927f --- /dev/null +++ b/src/main/java/konkuk/thip/notification/application/service/FcmDeleteService.java @@ -0,0 +1,22 @@ +package konkuk.thip.notification.application.service; + +import konkuk.thip.notification.application.port.in.FcmDeleteUseCase; +import konkuk.thip.notification.application.port.in.dto.FcmTokenDeleteCommand; +import konkuk.thip.notification.application.port.out.FcmTokenLoadPort; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class FcmDeleteService implements FcmDeleteUseCase { + + private final FcmTokenLoadPort fcmTokenLoadPort; + + + @Override + @Transactional + public void deleteToken(FcmTokenDeleteCommand command) { + fcmTokenLoadPort.deleteByUserIdAndDeviceId(command.userId(), command.deviceId()); + } +} From 1108eaca89c6ca87277e5b6e41212ef38a522935 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 3 Sep 2025 15:47:08 +0900 Subject: [PATCH 18/93] =?UTF-8?q?[feat]=20=ED=91=B8=EC=89=AC=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EC=97=AC=EB=B6=80=20=ED=99=9C=EC=84=B1/=EB=B9=84?= =?UTF-8?q?=ED=99=9C=EC=84=B1=ED=99=94=20=EC=84=A4=EC=A0=95=20dto=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/request/FcmTokenEnableStateChangeRequest.java | 10 +++++++++- .../response/FcmTokenEnableStateChangeResponse.java | 9 +++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/main/java/konkuk/thip/notification/adapter/in/web/response/FcmTokenEnableStateChangeResponse.java diff --git a/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenEnableStateChangeRequest.java b/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenEnableStateChangeRequest.java index fe0f5ab02..9f1031b3b 100644 --- a/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenEnableStateChangeRequest.java +++ b/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenEnableStateChangeRequest.java @@ -1,13 +1,21 @@ package konkuk.thip.notification.adapter.in.web.request; import io.swagger.v3.oas.annotations.media.Schema; +import konkuk.thip.notification.application.port.in.dto.FcmEnableStateChangeCommand; @Schema(description = "ํ‘ธ์‹œ ์•Œ๋ฆผ ์„ค์ • ๋ณ€๊ฒฝ ์š”์ฒญ DTO") public record FcmTokenEnableStateChangeRequest( @Schema(description = "ํ‘ธ์‹œ ์•Œ๋ฆผ ์ˆ˜์‹  ์—ฌ๋ถ€", example = "true") - boolean isEnable, + boolean enable, @Schema(description = "๋””๋ฐ”์ด์Šค ๊ณ ์œ  ID", example = "device12345") String deviceId ) { + public FcmEnableStateChangeCommand toCommand(Long userId) { + return new FcmEnableStateChangeCommand( + userId, + this.enable, + this.deviceId + ); + } } diff --git a/src/main/java/konkuk/thip/notification/adapter/in/web/response/FcmTokenEnableStateChangeResponse.java b/src/main/java/konkuk/thip/notification/adapter/in/web/response/FcmTokenEnableStateChangeResponse.java new file mode 100644 index 000000000..1a4ee24a8 --- /dev/null +++ b/src/main/java/konkuk/thip/notification/adapter/in/web/response/FcmTokenEnableStateChangeResponse.java @@ -0,0 +1,9 @@ +package konkuk.thip.notification.adapter.in.web.response; + +public record FcmTokenEnableStateChangeResponse( + boolean isEnabled +) { + public static FcmTokenEnableStateChangeResponse of(boolean isEnabled) { + return new FcmTokenEnableStateChangeResponse(isEnabled); + } +} From d868d4045f47c307c6fba47951c7baea1ecfe1a5 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 3 Sep 2025 15:47:49 +0900 Subject: [PATCH 19/93] =?UTF-8?q?[refactor]=20dto=20=EB=84=A4=EC=9D=B4?= =?UTF-8?q?=EB=B0=8D=20=EC=88=98=EC=A0=95,=20port=20default=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=A0=95=EC=9D=98=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...uest.java => FcmTokenRegisterRequest.java} | 10 +++++----- .../FcmTokenLoadPersistenceAdapter.java | 19 ++++--------------- .../port/out/FcmTokenLoadPort.java | 9 ++++++++- 3 files changed, 17 insertions(+), 21 deletions(-) rename src/main/java/konkuk/thip/notification/adapter/in/web/request/{FcmTokenRequest.java => FcmTokenRegisterRequest.java} (74%) diff --git a/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenRequest.java b/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenRegisterRequest.java similarity index 74% rename from src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenRequest.java rename to src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenRegisterRequest.java index 86c65bbad..b9897d1df 100644 --- a/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenRequest.java +++ b/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenRegisterRequest.java @@ -5,7 +5,7 @@ import konkuk.thip.notification.application.port.in.dto.FcmTokenRegisterCommand; @Schema(description = "FCM ํ† ํฐ ๋“ฑ๋ก ์š”์ฒญ DTO") -public record FcmTokenRequest( +public record FcmTokenRegisterRequest( @Schema(description = "๋””๋ฐ”์ด์Šค ๊ณ ์œ  ID", example = "device12345") String deviceId, @@ -15,11 +15,11 @@ public record FcmTokenRequest( @Schema(description = "ํ”Œ๋žซํผ ํƒ€์ž… (ANDROID ๋˜๋Š” WEB)", example = "ANDROID") PlatformType platformType ) { - public static FcmTokenRegisterCommand toCommand(FcmTokenRequest request, Long userId) { + public FcmTokenRegisterCommand toCommand(Long userId) { return FcmTokenRegisterCommand.builder() - .deviceId(request.deviceId) - .fcmToken(request.fcmToken) - .platformType(request.platformType) + .deviceId(this.deviceId) + .fcmToken(this.fcmToken) + .platformType(this.platformType) .userId(userId) .build(); } diff --git a/src/main/java/konkuk/thip/notification/adapter/out/persistence/FcmTokenLoadPersistenceAdapter.java b/src/main/java/konkuk/thip/notification/adapter/out/persistence/FcmTokenLoadPersistenceAdapter.java index d7548e781..8a4275755 100644 --- a/src/main/java/konkuk/thip/notification/adapter/out/persistence/FcmTokenLoadPersistenceAdapter.java +++ b/src/main/java/konkuk/thip/notification/adapter/out/persistence/FcmTokenLoadPersistenceAdapter.java @@ -32,7 +32,7 @@ public Optional findByDeviceId(String deviceId) { @Override public FcmToken save(FcmToken token) { - UserJpaEntity user = userJpaRepository.findById(token.getUserId()) + UserJpaEntity user = userJpaRepository.findByUserId(token.getUserId()) .orElseThrow(() -> new EntityNotFoundException(ErrorCode.USER_NOT_FOUND)); var saved = fcmTokenJpaRepository.save(fcmTokenMapper.toJpaEntity(token, user)); @@ -41,7 +41,7 @@ public FcmToken save(FcmToken token) { @Override public void update(FcmToken fcmToken) { - UserJpaEntity userJpaEntity = userJpaRepository.findById(fcmToken.getUserId()) + UserJpaEntity userJpaEntity = userJpaRepository.findByUserId(fcmToken.getUserId()) .orElseThrow(() -> new EntityNotFoundException(ErrorCode.USER_NOT_FOUND)); FcmTokenJpaEntity fcmTokenJpaEntity = fcmTokenJpaRepository.findByFcmTokenId(fcmToken.getId()) @@ -58,18 +58,7 @@ public List findEnabledByUserId(Long userId) { } @Override - public void disableById(Long id, String reason) { - var entity = fcmTokenJpaRepository.findById(id).orElse(null); - if (entity == null) return; - var disabled = FcmTokenJpaEntity.builder() - .fcmTokenId(entity.getFcmTokenId()) - .fcmToken(entity.getFcmToken()) - .deviceId(entity.getDeviceId()) - .platformType(entity.getPlatformType()) - .lastUsedTime(entity.getLastUsedTime()) - .isEnabled(false) - .userJpaEntity(entity.getUserJpaEntity()) - .build(); - fcmTokenJpaRepository.save(disabled); + public void deleteByUserIdAndDeviceId(Long userId, String deviceId) { + fcmTokenJpaRepository.deleteByUserIdAndDeviceId(userId, deviceId); } } diff --git a/src/main/java/konkuk/thip/notification/application/port/out/FcmTokenLoadPort.java b/src/main/java/konkuk/thip/notification/application/port/out/FcmTokenLoadPort.java index 18d81a7ba..388623c6c 100644 --- a/src/main/java/konkuk/thip/notification/application/port/out/FcmTokenLoadPort.java +++ b/src/main/java/konkuk/thip/notification/application/port/out/FcmTokenLoadPort.java @@ -1,5 +1,7 @@ package konkuk.thip.notification.application.port.out; +import konkuk.thip.common.exception.EntityNotFoundException; +import konkuk.thip.common.exception.code.ErrorCode; import konkuk.thip.notification.domain.FcmToken; import java.util.List; @@ -8,11 +10,16 @@ public interface FcmTokenLoadPort { Optional findByDeviceId(String deviceId); + default FcmToken getByDeviceIdOrThrow(String deviceId) { + return findByDeviceId(deviceId) + .orElseThrow(() -> new EntityNotFoundException(ErrorCode.FCM_TOKEN_NOT_FOUND)); + } + FcmToken save(FcmToken token); void update(FcmToken fcmToken); List findEnabledByUserId(Long userId); - void disableById(Long id, String reason); + void deleteByUserIdAndDeviceId(Long userId, String deviceId); } From 138c66f1dbae95972dd3278ef99fc1dcde479e0f Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 3 Sep 2025 15:48:05 +0900 Subject: [PATCH 20/93] =?UTF-8?q?[feat]=20fcm=20token=20=EC=82=AD=EC=A0=9C?= =?UTF-8?q?=20=EC=BF=BC=EB=A6=AC=20=EC=B6=94=EA=B0=80=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../out/persistence/repository/FcmTokenJpaRepository.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/konkuk/thip/notification/adapter/out/persistence/repository/FcmTokenJpaRepository.java b/src/main/java/konkuk/thip/notification/adapter/out/persistence/repository/FcmTokenJpaRepository.java index e58594525..f7f0d09c7 100644 --- a/src/main/java/konkuk/thip/notification/adapter/out/persistence/repository/FcmTokenJpaRepository.java +++ b/src/main/java/konkuk/thip/notification/adapter/out/persistence/repository/FcmTokenJpaRepository.java @@ -2,6 +2,7 @@ import konkuk.thip.notification.adapter.out.jpa.FcmTokenJpaEntity; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import java.util.List; @@ -16,4 +17,8 @@ public interface FcmTokenJpaRepository extends JpaRepository findByUserIdAndIsEnabledTrue(Long userId); Optional findByFcmTokenId(Long id); + + @Modifying + @Query("DELETE FROM FcmTokenJpaEntity f WHERE f.userJpaEntity.userId = :userId AND f.deviceId = :deviceId") + void deleteByUserIdAndDeviceId(Long userId, String deviceId); } From 70e2ecad2e6a9a259309b76896f26213cf5b2320 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 3 Sep 2025 15:48:17 +0900 Subject: [PATCH 21/93] =?UTF-8?q?[docs]=20=EC=8A=A4=EC=9B=A8=EA=B1=B0=20?= =?UTF-8?q?=EB=AA=85=EC=84=B8=20=EC=B6=94=EA=B0=80=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../konkuk/thip/common/exception/code/ErrorCode.java | 5 +++++ .../common/swagger/SwaggerResponseDescription.java | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java b/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java index 7e340d759..0b608689a 100644 --- a/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java +++ b/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java @@ -211,6 +211,11 @@ public enum ErrorCode implements ResponseCode { ATTENDANCE_CHECK_NOT_FOUND(HttpStatus.NOT_FOUND, 195001, "์กด์žฌํ•˜์ง€ ์•Š๋Š” ATTENDANCE CHECK ์ž…๋‹ˆ๋‹ค."), ATTENDANCE_CHECK_CAN_NOT_DELETE(HttpStatus.FORBIDDEN, 195002, "์˜ค๋Š˜์˜ ํ•œ๋งˆ๋””๋Š” ๋ณธ์ธ๋งŒ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค."), + /** + * 200000 : Fcm error + */ + FCM_TOKEN_NOT_FOUND(HttpStatus.NOT_FOUND, 200000, "์กด์žฌํ•˜์ง€ ์•Š๋Š” FCM TOKEN ์ž…๋‹ˆ๋‹ค."), + FCM_TOKEN_ENABLED_STATE_ALREADY(HttpStatus.BAD_REQUEST, 200001, "์š”์ฒญํ•œ ์ƒํƒœ๋กœ ์ด๋ฏธ ํ‘ธ์‰ฌ์•Œ๋ฆผ ์—ฌ๋ถ€๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค."), ; diff --git a/src/main/java/konkuk/thip/common/swagger/SwaggerResponseDescription.java b/src/main/java/konkuk/thip/common/swagger/SwaggerResponseDescription.java index a8d26d610..db2fc8e09 100644 --- a/src/main/java/konkuk/thip/common/swagger/SwaggerResponseDescription.java +++ b/src/main/java/konkuk/thip/common/swagger/SwaggerResponseDescription.java @@ -329,6 +329,17 @@ public enum SwaggerResponseDescription { ATTENDANCE_CHECK_CAN_NOT_DELETE ))), + // Notiification + FCM_TOKEN_REGISTER(new LinkedHashSet<>(Set.of( + USER_NOT_FOUND, + FCM_TOKEN_NOT_FOUND + ))), + FCM_TOKEN_ENABLE_STATE_CHANGE(new LinkedHashSet<>(Set.of( + USER_NOT_FOUND, + FCM_TOKEN_NOT_FOUND, + FCM_TOKEN_ENABLED_STATE_ALREADY + ))), + ; private final Set errorCodeList; SwaggerResponseDescription(Set errorCodeList) { From 421a90e5a15f67c2bf475b5ff0cf3ce223ef644c Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Wed, 3 Sep 2025 15:49:12 +0900 Subject: [PATCH 22/93] =?UTF-8?q?[refactor]=20=EC=95=88=EC=93=B0=EB=8A=94?= =?UTF-8?q?=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=82=AD=EC=A0=9C=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/in/web/response/DummyResponse.java | 7 ------- .../application/port/in/dto/DummyCommand.java | 10 ---------- .../application/port/in/dto/DummyQuery.java | 9 --------- .../application/port/in/dto/DummyResult.java | 10 ---------- 4 files changed, 36 deletions(-) delete mode 100644 src/main/java/konkuk/thip/notification/adapter/in/web/response/DummyResponse.java delete mode 100644 src/main/java/konkuk/thip/notification/application/port/in/dto/DummyCommand.java delete mode 100644 src/main/java/konkuk/thip/notification/application/port/in/dto/DummyQuery.java delete mode 100644 src/main/java/konkuk/thip/notification/application/port/in/dto/DummyResult.java diff --git a/src/main/java/konkuk/thip/notification/adapter/in/web/response/DummyResponse.java b/src/main/java/konkuk/thip/notification/adapter/in/web/response/DummyResponse.java deleted file mode 100644 index d5272cec1..000000000 --- a/src/main/java/konkuk/thip/notification/adapter/in/web/response/DummyResponse.java +++ /dev/null @@ -1,7 +0,0 @@ -package konkuk.thip.notification.adapter.in.web.response; - -import lombok.Getter; - -@Getter -public class DummyResponse { -} diff --git a/src/main/java/konkuk/thip/notification/application/port/in/dto/DummyCommand.java b/src/main/java/konkuk/thip/notification/application/port/in/dto/DummyCommand.java deleted file mode 100644 index c5c44a118..000000000 --- a/src/main/java/konkuk/thip/notification/application/port/in/dto/DummyCommand.java +++ /dev/null @@ -1,10 +0,0 @@ -package konkuk.thip.notification.application.port.in.dto; - -import lombok.Builder; -import lombok.Getter; - -@Builder -@Getter -public class DummyCommand { - -} diff --git a/src/main/java/konkuk/thip/notification/application/port/in/dto/DummyQuery.java b/src/main/java/konkuk/thip/notification/application/port/in/dto/DummyQuery.java deleted file mode 100644 index 1b8879fd7..000000000 --- a/src/main/java/konkuk/thip/notification/application/port/in/dto/DummyQuery.java +++ /dev/null @@ -1,9 +0,0 @@ -package konkuk.thip.notification.application.port.in.dto; - -import lombok.Builder; -import lombok.Getter; - -@Builder -@Getter -public class DummyQuery { -} diff --git a/src/main/java/konkuk/thip/notification/application/port/in/dto/DummyResult.java b/src/main/java/konkuk/thip/notification/application/port/in/dto/DummyResult.java deleted file mode 100644 index 4f6005404..000000000 --- a/src/main/java/konkuk/thip/notification/application/port/in/dto/DummyResult.java +++ /dev/null @@ -1,10 +0,0 @@ -package konkuk.thip.notification.application.port.in.dto; - -import lombok.Builder; -import lombok.Getter; - -@Getter -@Builder -public class DummyResult { - -} From 1031d23d8d6038380b6c029fea210fbc4efa5cc9 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 4 Sep 2025 18:31:18 +0900 Subject: [PATCH 23/93] =?UTF-8?q?[chore]=20FcmToken=20=ED=85=8C=EC=9D=B4?= =?UTF-8?q?=EB=B8=94=20=EC=B6=94=EA=B0=80=20ddl=20=EC=BF=BC=EB=A6=AC=20(#2?= =?UTF-8?q?89)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../db/migration/V250828__Add_room_status.sql | 2 +- .../migration/V250904__Create_FcmToken_table.sql | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/db/migration/V250904__Create_FcmToken_table.sql diff --git a/src/main/resources/db/migration/V250828__Add_room_status.sql b/src/main/resources/db/migration/V250828__Add_room_status.sql index 0110d59de..23a57aedd 100644 --- a/src/main/resources/db/migration/V250828__Add_room_status.sql +++ b/src/main/resources/db/migration/V250828__Add_room_status.sql @@ -11,4 +11,4 @@ WHERE start_date <= CURDATE(); -- 3) end_date๊ฐ€ ํ˜„์žฌ ๋‚ ์งœ๋ณด๋‹ค "์ด์ „"์ด๋ฉด EXPIRED๋กœ ์—…๋ฐ์ดํŠธ UPDATE rooms SET room_status = 'EXPIRED' -WHERE end_date < CURDATE(); \ No newline at end of file +WHERE end_date < CURDATE(); diff --git a/src/main/resources/db/migration/V250904__Create_FcmToken_table.sql b/src/main/resources/db/migration/V250904__Create_FcmToken_table.sql new file mode 100644 index 000000000..22d491380 --- /dev/null +++ b/src/main/resources/db/migration/V250904__Create_FcmToken_table.sql @@ -0,0 +1,15 @@ +CREATE TABLE fcm_tokens ( + fcm_token_id BIGINT AUTO_INCREMENT PRIMARY KEY, + fcm_token VARCHAR(255) NOT NULL, + device_id VARCHAR(128) NOT NULL UNIQUE, + platform VARCHAR(16) NOT NULL, + last_used_time DATE NOT NULL, + is_enabled BOOLEAN NOT NULL, + user_id BIGINT NOT NULL, + created_at DATETIME(6) NOT NULL, + modified_at DATETIME(6) NOT NULL, + status VARCHAR(32) NOT NULL DEFAULT 'ACTIVE', + CONSTRAINT fk_fcm_tokens_user + FOREIGN KEY (user_id) REFERENCES users(user_id) + ON DELETE CASCADE +); \ No newline at end of file From 628a502199774326a39c9215bb14a44067abd1c7 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 4 Sep 2025 18:31:56 +0900 Subject: [PATCH 24/93] =?UTF-8?q?[feat]=20EventListener=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../in/event/MessageFeedEventListener.java | 53 +++++++++++++++ .../in/event/MessageRoomEventListener.java | 64 +++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 src/main/java/konkuk/thip/message/adapter/in/event/MessageFeedEventListener.java create mode 100644 src/main/java/konkuk/thip/message/adapter/in/event/MessageRoomEventListener.java diff --git a/src/main/java/konkuk/thip/message/adapter/in/event/MessageFeedEventListener.java b/src/main/java/konkuk/thip/message/adapter/in/event/MessageFeedEventListener.java new file mode 100644 index 000000000..b3087a7cf --- /dev/null +++ b/src/main/java/konkuk/thip/message/adapter/in/event/MessageFeedEventListener.java @@ -0,0 +1,53 @@ +// notification/adapter/in/event/NotificationEventHandler.java (๋ฐœ์ทŒ: Room ๊ด€๋ จ ๋ฉ”์„œ๋“œ๋งŒ) +package konkuk.thip.message.adapter.in.event; + +import konkuk.thip.message.adapter.out.event.dto.FeedEvents; +import konkuk.thip.message.application.port.in.FeedNotificationDispatchUseCase; +import lombok.RequiredArgsConstructor; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.transaction.event.TransactionPhase; +import org.springframework.transaction.event.TransactionalEventListener; + +@Component +@RequiredArgsConstructor +public class MessageFeedEventListener { + + private final FeedNotificationDispatchUseCase feedUseCase; + + @Async + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void onFollower(FeedEvents.FollowerEvent e) { + feedUseCase.handleFollower(e); + } + + @Async + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void onFeedCommented(FeedEvents.FeedCommentedEvent e) { + feedUseCase.handleFeedCommented(e); + } + + @Async + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void onFeedReplied(FeedEvents.FeedRepliedEvent e) { + feedUseCase.handleFeedReplied(e); + } + + @Async + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void onFolloweeNewPost(FeedEvents.FolloweeNewPostEvent e) { + feedUseCase.handleFolloweeNewPost(e); + } + + @Async + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void onFeedLiked(FeedEvents.FeedLikedEvent e) { + feedUseCase.handleFeedLiked(e); + } + + @Async + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void onFeedCommentLiked(FeedEvents.FeedCommentLikedEvent e) { + feedUseCase.handleFeedCommentLiked(e); + } +} \ No newline at end of file diff --git a/src/main/java/konkuk/thip/message/adapter/in/event/MessageRoomEventListener.java b/src/main/java/konkuk/thip/message/adapter/in/event/MessageRoomEventListener.java new file mode 100644 index 000000000..dd747fe46 --- /dev/null +++ b/src/main/java/konkuk/thip/message/adapter/in/event/MessageRoomEventListener.java @@ -0,0 +1,64 @@ +package konkuk.thip.message.adapter.in.event; + +import konkuk.thip.message.adapter.out.event.dto.RoomEvents; +import konkuk.thip.message.application.port.in.RoomNotificationDispatchUseCase; +import lombok.RequiredArgsConstructor; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.transaction.event.TransactionPhase; +import org.springframework.transaction.event.TransactionalEventListener; + +@Component +@RequiredArgsConstructor +public class MessageRoomEventListener { + + private final RoomNotificationDispatchUseCase roomUseCase; + + @Async + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void onRoomRecordCommented(RoomEvents.RoomRecordCommentedEvent e) { + roomUseCase.handleRoomRecordCommented(e); + } + + @Async + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void onRoomVoteStarted(RoomEvents.RoomVoteStartedEvent e) { + roomUseCase.handleRoomVoteStarted(e); + } + + @Async + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void onRoomRecordCreated(RoomEvents.RoomRecordCreatedEvent e) { + roomUseCase.handleRoomRecordCreated(e); + } + + @Async + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void onRoomRecruitClosedEarly(RoomEvents.RoomRecruitClosedEarlyEvent e) { + roomUseCase.handleRoomRecruitClosedEarly(e); + } + + @Async + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void onRoomActivityStarted(RoomEvents.RoomActivityStartedEvent e) { + roomUseCase.handleRoomActivityStarted(e); + } + + @Async + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void onRoomJoinRequestedToOwner(RoomEvents.RoomJoinRequestedToOwnerEvent e) { + roomUseCase.handleRoomJoinRequestedToOwner(e); + } + + @Async + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void onRoomCommentLiked(RoomEvents.RoomCommentLikedEvent e) { + roomUseCase.handleRoomCommentLiked(e); + } + + @Async + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void onRoomRecordLiked(RoomEvents.RoomRecordLikedEvent e) { + roomUseCase.handleRoomRecordLiked(e); + } +} From a9743d1379cd374849e6dfca910e7812a999d410 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 4 Sep 2025 18:32:29 +0900 Subject: [PATCH 25/93] =?UTF-8?q?[feat]=20=ED=91=B8=EC=89=AC=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EB=B0=9C=ED=96=89=20?= =?UTF-8?q?adapter=20=EC=A0=95=EC=9D=98=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../out/event/FeedEventPublisherAdapter.java | 78 ++++++++++++ .../out/event/RoomEventPublisherAdapter.java | 111 ++++++++++++++++++ .../port/out/FeedEventCommandPort.java | 27 +++++ .../port/out/RoomEventCommandPort.java | 34 ++++++ 4 files changed, 250 insertions(+) create mode 100644 src/main/java/konkuk/thip/message/adapter/out/event/FeedEventPublisherAdapter.java create mode 100644 src/main/java/konkuk/thip/message/adapter/out/event/RoomEventPublisherAdapter.java create mode 100644 src/main/java/konkuk/thip/message/application/port/out/FeedEventCommandPort.java create mode 100644 src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java diff --git a/src/main/java/konkuk/thip/message/adapter/out/event/FeedEventPublisherAdapter.java b/src/main/java/konkuk/thip/message/adapter/out/event/FeedEventPublisherAdapter.java new file mode 100644 index 000000000..285fc7008 --- /dev/null +++ b/src/main/java/konkuk/thip/message/adapter/out/event/FeedEventPublisherAdapter.java @@ -0,0 +1,78 @@ +package konkuk.thip.message.adapter.out.event; + +import konkuk.thip.message.adapter.out.event.dto.FeedEvents; +import konkuk.thip.message.application.port.out.FeedEventCommandPort; +import lombok.RequiredArgsConstructor; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class FeedEventPublisherAdapter implements FeedEventCommandPort { + + private final ApplicationEventPublisher publisher; + + @Override + public void publishFollowEvent(Long targetUserId, Long actorUserId, String actorUsername) { + publisher.publishEvent(FeedEvents.FollowerEvent.builder() + .targetUserId(targetUserId) + .actorUserId(actorUserId) + .actorUsername(actorUsername) + .build()); + } + + @Override + public void publishFeedCommentedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long feedId) { + publisher.publishEvent(FeedEvents.FeedCommentedEvent.builder() + .targetUserId(targetUserId) + .actorUserId(actorUserId) + .actorUsername(actorUsername) + .feedId(feedId) + .build()); + } + + @Override + public void publishFeedRepliedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long feedId) { + publisher.publishEvent(FeedEvents.FeedRepliedEvent.builder() + .targetUserId(targetUserId) + .actorUserId(actorUserId) + .actorUsername(actorUsername) + .feedId(feedId) + .build()); + } + + @Override + public void publishFolloweeNewPostEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long feedId) { + publisher.publishEvent(FeedEvents.FolloweeNewPostEvent.builder() + .targetUserId(targetUserId) + .actorUserId(actorUserId) + .actorUsername(actorUsername) + .feedId(feedId) + .build()); + } + + @Override + public void publishFeedLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long feedId) { + publisher.publishEvent(FeedEvents.FeedLikedEvent.builder() + .targetUserId(targetUserId) + .actorUserId(actorUserId) + .actorUsername(actorUsername) + .feedId(feedId) + .build()); + } + + @Override + public void publishFeedCommentLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long feedId) { + publisher.publishEvent(FeedEvents.FeedCommentLikedEvent.builder() + .targetUserId(targetUserId) + .actorUserId(actorUserId) + .actorUsername(actorUsername) + .feedId(feedId) + .build()); + } +} \ No newline at end of file diff --git a/src/main/java/konkuk/thip/message/adapter/out/event/RoomEventPublisherAdapter.java b/src/main/java/konkuk/thip/message/adapter/out/event/RoomEventPublisherAdapter.java new file mode 100644 index 000000000..8d2620b2b --- /dev/null +++ b/src/main/java/konkuk/thip/message/adapter/out/event/RoomEventPublisherAdapter.java @@ -0,0 +1,111 @@ +package konkuk.thip.message.adapter.out.event; + +import konkuk.thip.message.adapter.out.event.dto.RoomEvents; +import konkuk.thip.message.application.port.out.RoomEventCommandPort; +import lombok.RequiredArgsConstructor; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +public class RoomEventPublisherAdapter implements RoomEventCommandPort { + + private final ApplicationEventPublisher publisher; + + @Override + public void publishRoomRecordCommentedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long roomId, Integer page, Long postId, String postType) { + publisher.publishEvent(RoomEvents.RoomRecordCommentedEvent.builder() + .targetUserId(targetUserId) + .actorUserId(actorUserId) + .actorUsername(actorUsername) + .roomId(roomId) + .page(page) + .postId(postId) + .postType(postType) + .build()); + } + + @Override + public void publishRoomVoteStartedEvent(Long targetUserId, Long roomId, String roomTitle, + Integer page, Long postId) { + publisher.publishEvent(RoomEvents.RoomVoteStartedEvent.builder() + .targetUserId(targetUserId) + .roomId(roomId) + .roomTitle(roomTitle) + .page(page) + .postId(postId) + .build()); + } + + @Override + public void publishRoomRecordCreatedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long roomId, String roomTitle, Integer page, Long postId) { + publisher.publishEvent(RoomEvents.RoomRecordCreatedEvent.builder() + .targetUserId(targetUserId) + .actorUserId(actorUserId) + .actorUsername(actorUsername) + .roomId(roomId) + .roomTitle(roomTitle) + .page(page) + .postId(postId) + .build()); + } + + @Override + public void publishRoomRecruitClosedEarlyEvent(Long targetUserId, Long roomId, String roomTitle) { + publisher.publishEvent(RoomEvents.RoomRecruitClosedEarlyEvent.builder() + .targetUserId(targetUserId) + .roomId(roomId) + .roomTitle(roomTitle) + .build()); + } + + @Override + public void publishRoomActivityStartedEvent(Long targetUserId, Long roomId, String roomTitle) { + publisher.publishEvent(RoomEvents.RoomActivityStartedEvent.builder() + .targetUserId(targetUserId) + .roomId(roomId) + .roomTitle(roomTitle) + .build()); + } + + @Override + public void publishRoomJoinEventToHost(Long ownerUserId, Long roomId, String roomTitle, + Long applicantUserId, String applicantUsername) { + publisher.publishEvent(RoomEvents.RoomJoinRequestedToOwnerEvent.builder() + .ownerUserId(ownerUserId) + .roomId(roomId) + .roomTitle(roomTitle) + .applicantUserId(applicantUserId) + .applicantUsername(applicantUsername) + .build()); + } + + @Override + public void publishRoomCommentLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long roomId, Integer page, Long postId) { + publisher.publishEvent(RoomEvents.RoomCommentLikedEvent.builder() + .targetUserId(targetUserId) + .actorUserId(actorUserId) + .actorUsername(actorUsername) + .roomId(roomId) + .page(page) + .postId(postId) + .build()); + } + + @Override + public void publishRoomRecordLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long roomId, Integer page, Long postId, String postType) { + publisher.publishEvent(RoomEvents.RoomRecordLikedEvent.builder() + .targetUserId(targetUserId) + .actorUserId(actorUserId) + .actorUsername(actorUsername) + .roomId(roomId) + .page(page) + .postId(postId) + .postType(postType) + .build()); + } +} \ No newline at end of file diff --git a/src/main/java/konkuk/thip/message/application/port/out/FeedEventCommandPort.java b/src/main/java/konkuk/thip/message/application/port/out/FeedEventCommandPort.java new file mode 100644 index 000000000..0fbc5631d --- /dev/null +++ b/src/main/java/konkuk/thip/message/application/port/out/FeedEventCommandPort.java @@ -0,0 +1,27 @@ +package konkuk.thip.message.application.port.out; + +public interface FeedEventCommandPort { + + // ๋ˆ„๊ตฐ๊ฐ€ ๋‚˜๋ฅผ ํŒ”๋กœ์šฐํ•˜๋Š” ๊ฒฝ์šฐ + void publishFollowEvent(Long targetUserId, Long actorUserId, String actorUsername); + + // ๋ˆ„๊ตฐ๊ฐ€ ๋‚ด ํ”ผ๋“œ์— ๋Œ“๊ธ€์„ ๋‹ค๋Š” ๊ฒฝ์šฐ + void publishFeedCommentedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long feedId); + + // ๋ˆ„๊ตฐ๊ฐ€ ๋‚ด ๋Œ“๊ธ€์— ๋Œ€๋Œ“๊ธ€์„ ๋‹ค๋Š” ๊ฒฝ์šฐ + void publishFeedRepliedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long feedId); + + // ๋‚ด๊ฐ€ ํŒ”๋กœ์šฐํ•˜๋Š” ์‚ฌ๋žŒ์ด ์ƒˆ ๊ธ€์„ ์˜ฌ๋ฆฌ๋Š” ๊ฒฝ์šฐ + void publishFolloweeNewPostEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long feedId); + + // ๋‚ด ํ”ผ๋“œ๊ฐ€ ์ข‹์•„์š”๋ฅผ ๋ฐ›๋Š” ๊ฒฝ์šฐ + void publishFeedLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long feedId); + + // ๋‚ด ํ”ผ๋“œ ๋Œ“๊ธ€์ด ์ข‹์•„์š”๋ฅผ ๋ฐ›๋Š” ๊ฒฝ์šฐ + void publishFeedCommentLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long feedId); +} \ No newline at end of file diff --git a/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java b/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java new file mode 100644 index 000000000..a7450abe5 --- /dev/null +++ b/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java @@ -0,0 +1,34 @@ +package konkuk.thip.message.application.port.out; + +public interface RoomEventCommandPort { + + // ๋‚ด ๋ชจ์ž„๋ฐฉ ๊ธฐ๋ก/ํˆฌํ‘œ์— ๋Œ“๊ธ€์ด ๋‹ฌ๋ฆฐ ๊ฒฝ์šฐ + void publishRoomRecordCommentedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long roomId, Integer page, Long postId, String postType); + + // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ์— ์ƒˆ๋กœ์šด ํˆฌํ‘œ๊ฐ€ ์‹œ์ž‘๋œ ๊ฒฝ์šฐ + void publishRoomVoteStartedEvent(Long targetUserId, Long roomId, String roomTitle, + Integer page, Long postId); + + // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ์— ์ƒˆ๋กœ์šด ๊ธฐ๋ก์ด ์ž‘์„ฑ๋œ ๊ฒฝ์šฐ + void publishRoomRecordCreatedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long roomId, String roomTitle, Integer page, Long postId); + + // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ์ด ์กฐ๊ธฐ ์ข…๋ฃŒ๋œ ๊ฒฝ์šฐ (ํ˜ธ์ŠคํŠธ๊ฐ€ ๋ชจ์ง‘ ๋งˆ๊ฐ ๋ฒ„ํŠผ ๋ˆ„๋ฅธ ๊ฒฝ์šฐ) + void publishRoomRecruitClosedEarlyEvent(Long targetUserId, Long roomId, String roomTitle); + + // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ ํ™œ๋™์ด ์‹œ์ž‘๋œ ๊ฒฝ์šฐ (๋ฐฉ์ด ์‹œ์ž‘ ๊ธฐ๊ฐ„์ด ๋˜์–ด ์ž๋™์œผ๋กœ ์‹œ์ž‘๋œ ๊ฒฝ์šฐ) + void publishRoomActivityStartedEvent(Long targetUserId, Long roomId, String roomTitle); + + // ๋‚ด๊ฐ€ ๋ฐฉ์žฅ์ผ ๋•Œ, ์ƒˆ๋กœ์šด ์‚ฌ์šฉ์ž๊ฐ€ ๋ชจ์ž„๋ฐฉ ์ฐธ์—ฌ๋ฅผ ํ•œ ๊ฒฝ์šฐ + void publishRoomJoinEventToHost(Long ownerUserId, Long roomId, String roomTitle, + Long applicantUserId, String applicantUsername); + + // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ์˜ ๋‚˜์˜ ๋Œ“๊ธ€์ด ์ข‹์•„์š”๋ฅผ ๋ฐ›๋Š” ๊ฒฝ์šฐ + void publishRoomCommentLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long roomId, Integer page, Long postId); + + // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ ์•ˆ์˜ ๋‚˜์˜ ๊ธฐ๋ก/ํˆฌํ‘œ๊ฐ€ ์ข‹์•„์š”๋ฅผ ๋ฐ›๋Š” ๊ฒฝ์šฐ + void publishRoomRecordLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long roomId, Integer page, Long postId, String postType); +} \ No newline at end of file From 4a26f10f58609dbd456274eca356769a5df1762c Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 4 Sep 2025 18:33:04 +0900 Subject: [PATCH 26/93] =?UTF-8?q?[feat]=20Event=20=EC=A0=95=EC=9D=98=20(#2?= =?UTF-8?q?89)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/out/event/dto/FeedEvents.java | 36 +++++++++++++++ .../adapter/out/event/dto/RoomEvents.java | 46 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 src/main/java/konkuk/thip/message/adapter/out/event/dto/FeedEvents.java create mode 100644 src/main/java/konkuk/thip/message/adapter/out/event/dto/RoomEvents.java diff --git a/src/main/java/konkuk/thip/message/adapter/out/event/dto/FeedEvents.java b/src/main/java/konkuk/thip/message/adapter/out/event/dto/FeedEvents.java new file mode 100644 index 000000000..c687bd6c2 --- /dev/null +++ b/src/main/java/konkuk/thip/message/adapter/out/event/dto/FeedEvents.java @@ -0,0 +1,36 @@ +// message/adapter/out/event/dto/FeedEvents.java +package konkuk.thip.message.adapter.out.event.dto; + +import lombok.Builder; + +public class FeedEvents { + + // ๋ˆ„๊ตฐ๊ฐ€ ๋‚˜๋ฅผ ํŒ”๋กœ์šฐํ•˜๋Š” ๊ฒฝ์šฐ + @Builder + public record FollowerEvent(Long targetUserId, Long actorUserId, String actorUsername) {} + + // ๋ˆ„๊ตฐ๊ฐ€ ๋‚ด ํ”ผ๋“œ์— ๋Œ“๊ธ€์„ ๋‹ค๋Š” ๊ฒฝ์šฐ + @Builder + public record FeedCommentedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long feedId) {} + + // ๋ˆ„๊ตฐ๊ฐ€ ๋‚ด ๋Œ“๊ธ€์— ๋Œ€๋Œ“๊ธ€์„ ๋‹ค๋Š” ๊ฒฝ์šฐ + @Builder + public record FeedRepliedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long feedId) {} + + // ๋‚ด๊ฐ€ ํŒ”๋กœ์šฐํ•˜๋Š” ์‚ฌ๋žŒ์ด ์ƒˆ ๊ธ€์„ ์˜ฌ๋ฆฌ๋Š” ๊ฒฝ์šฐ + @Builder + public record FolloweeNewPostEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long feedId) {} + + // ๋‚ด ํ”ผ๋“œ๊ฐ€ ์ข‹์•„์š”๋ฅผ ๋ฐ›๋Š” ๊ฒฝ์šฐ + @Builder + public record FeedLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long feedId) {} + + // ๋‚ด ํ”ผ๋“œ ๋Œ“๊ธ€์ด ์ข‹์•„์š”๋ฅผ ๋ฐ›๋Š” ๊ฒฝ์šฐ + @Builder + public record FeedCommentLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long feedId) {} +} \ No newline at end of file diff --git a/src/main/java/konkuk/thip/message/adapter/out/event/dto/RoomEvents.java b/src/main/java/konkuk/thip/message/adapter/out/event/dto/RoomEvents.java new file mode 100644 index 000000000..1cd43bfc7 --- /dev/null +++ b/src/main/java/konkuk/thip/message/adapter/out/event/dto/RoomEvents.java @@ -0,0 +1,46 @@ +// message/adapter/out/event/dto/RoomEvents.java +package konkuk.thip.message.adapter.out.event.dto; + +import lombok.Builder; + +public class RoomEvents { + + // ๋Œ“๊ธ€ ๋Œ€์ƒ์ด "๊ธฐ๋ก/ํˆฌํ‘œ" ๋ชจ๋‘ ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ ํ†ตํ•ฉ ์Šคํ‚ค๋งˆ ์‚ฌ์šฉ + // ๋‚ด ๋ชจ์ž„๋ฐฉ ๊ธฐ๋ก/ํˆฌํ‘œ์— ๋Œ“๊ธ€์ด ๋‹ฌ๋ฆฐ ๊ฒฝ์šฐ + @Builder + public record RoomRecordCommentedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long roomId, Integer page, Long postId, String postType) {} + + // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ์— ์ƒˆ๋กœ์šด ํˆฌํ‘œ๊ฐ€ ์‹œ์ž‘๋œ ๊ฒฝ์šฐ + @Builder + public record RoomVoteStartedEvent(Long targetUserId, Long roomId, String roomTitle, + Integer page, Long postId) {} + + // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ์— ์ƒˆ๋กœ์šด ๊ธฐ๋ก์ด ์ž‘์„ฑ๋œ ๊ฒฝ์šฐ + @Builder + public record RoomRecordCreatedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long roomId, String roomTitle, Integer page, Long postId) {} + + // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ์ด ์กฐ๊ธฐ ์ข…๋ฃŒ๋œ ๊ฒฝ์šฐ (ํ˜ธ์ŠคํŠธ๊ฐ€ ๋ชจ์ง‘ ๋งˆ๊ฐ ๋ฒ„ํŠผ ๋ˆ„๋ฅธ ๊ฒฝ์šฐ) + @Builder + public record RoomRecruitClosedEarlyEvent(Long targetUserId, Long roomId, String roomTitle) {} + + // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ ํ™œ๋™์ด ์‹œ์ž‘๋œ ๊ฒฝ์šฐ (๋ฐฉ์ด ์‹œ์ž‘ ๊ธฐ๊ฐ„์ด ๋˜์–ด ์ž๋™์œผ๋กœ ์‹œ์ž‘๋œ ๊ฒฝ์šฐ) + @Builder + public record RoomActivityStartedEvent(Long targetUserId, Long roomId, String roomTitle) {} + + // ๋‚ด๊ฐ€ ๋ฐฉ์žฅ์ผ ๋•Œ, ์ƒˆ๋กœ์šด ์‚ฌ์šฉ์ž๊ฐ€ ๋ชจ์ž„๋ฐฉ ์ฐธ์—ฌ๋ฅผ ํ•œ ๊ฒฝ์šฐ + @Builder + public record RoomJoinRequestedToOwnerEvent(Long ownerUserId, Long roomId, String roomTitle, + Long applicantUserId, String applicantUsername) {} + + // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ์˜ ๋‚˜์˜ ๋Œ“๊ธ€์ด ์ข‹์•„์š”๋ฅผ ๋ฐ›๋Š” ๊ฒฝ์šฐ + @Builder + public record RoomCommentLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long roomId, Integer page, Long postId) {} + + // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ์˜ ๋‚˜์˜ ๊ธฐ๋ก์ด ์ข‹์•„์š”๋ฅผ ๋ฐ›๋Š” ๊ฒฝ์šฐ + @Builder + public record RoomRecordLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long roomId, Integer page, Long postId, String postType) {} +} \ No newline at end of file From e50c8be696ded0cf33d518b95a8f3580256e5901 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 4 Sep 2025 18:33:24 +0900 Subject: [PATCH 27/93] =?UTF-8?q?[feat]=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=ED=95=B8=EB=93=A4=EB=9F=AC=20=EC=84=9C=EB=B9=84=EC=8A=A4=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../in/FeedNotificationDispatchUseCase.java | 17 ++ .../in/RoomNotificationDispatchUseCase.java | 21 ++ .../FeedNotificationDispatchService.java | 127 ++++++++++ .../RoomNotificationDispatchService.java | 235 ++++++++++++++++++ 4 files changed, 400 insertions(+) create mode 100644 src/main/java/konkuk/thip/message/application/port/in/FeedNotificationDispatchUseCase.java create mode 100644 src/main/java/konkuk/thip/message/application/port/in/RoomNotificationDispatchUseCase.java create mode 100644 src/main/java/konkuk/thip/message/application/service/FeedNotificationDispatchService.java create mode 100644 src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java diff --git a/src/main/java/konkuk/thip/message/application/port/in/FeedNotificationDispatchUseCase.java b/src/main/java/konkuk/thip/message/application/port/in/FeedNotificationDispatchUseCase.java new file mode 100644 index 000000000..eba755db3 --- /dev/null +++ b/src/main/java/konkuk/thip/message/application/port/in/FeedNotificationDispatchUseCase.java @@ -0,0 +1,17 @@ +package konkuk.thip.message.application.port.in; + +import konkuk.thip.message.adapter.out.event.dto.FeedEvents; + +public interface FeedNotificationDispatchUseCase { + void handleFollower(FeedEvents.FollowerEvent e); + + void handleFeedCommented(FeedEvents.FeedCommentedEvent e); + + void handleFeedReplied(FeedEvents.FeedRepliedEvent e); + + void handleFolloweeNewPost(FeedEvents.FolloweeNewPostEvent e); + + void handleFeedLiked(FeedEvents.FeedLikedEvent e); + + void handleFeedCommentLiked(FeedEvents.FeedCommentLikedEvent e); +} \ No newline at end of file diff --git a/src/main/java/konkuk/thip/message/application/port/in/RoomNotificationDispatchUseCase.java b/src/main/java/konkuk/thip/message/application/port/in/RoomNotificationDispatchUseCase.java new file mode 100644 index 000000000..124ab1344 --- /dev/null +++ b/src/main/java/konkuk/thip/message/application/port/in/RoomNotificationDispatchUseCase.java @@ -0,0 +1,21 @@ +package konkuk.thip.message.application.port.in; + +import konkuk.thip.message.adapter.out.event.dto.RoomEvents; + +public interface RoomNotificationDispatchUseCase { + void handleRoomRecordCommented(RoomEvents.RoomRecordCommentedEvent e); + + void handleRoomVoteStarted(RoomEvents.RoomVoteStartedEvent e); + + void handleRoomRecordCreated(RoomEvents.RoomRecordCreatedEvent e); + + void handleRoomRecruitClosedEarly(RoomEvents.RoomRecruitClosedEarlyEvent e); + + void handleRoomActivityStarted(RoomEvents.RoomActivityStartedEvent e); + + void handleRoomJoinRequestedToOwner(RoomEvents.RoomJoinRequestedToOwnerEvent e); + + void handleRoomCommentLiked(RoomEvents.RoomCommentLikedEvent e); + + void handleRoomRecordLiked(RoomEvents.RoomRecordLikedEvent e); +} \ No newline at end of file diff --git a/src/main/java/konkuk/thip/message/application/service/FeedNotificationDispatchService.java b/src/main/java/konkuk/thip/message/application/service/FeedNotificationDispatchService.java new file mode 100644 index 000000000..20e9956ee --- /dev/null +++ b/src/main/java/konkuk/thip/message/application/service/FeedNotificationDispatchService.java @@ -0,0 +1,127 @@ +package konkuk.thip.message.application.service; + +import com.google.firebase.messaging.Message; +import com.google.firebase.messaging.Notification; +import konkuk.thip.message.application.port.in.FeedNotificationDispatchUseCase; +import konkuk.thip.message.application.port.out.FirebaseMessagingPort; +import konkuk.thip.message.adapter.out.event.dto.FeedEvents; +import konkuk.thip.message.domain.NotificationCategory; +import konkuk.thip.message.domain.MessageRoute; +import konkuk.thip.notification.application.port.out.FcmTokenLoadPort; +import konkuk.thip.notification.domain.FcmToken; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class FeedNotificationDispatchService implements FeedNotificationDispatchUseCase { + + private final FcmTokenLoadPort fcmTokenLoadPort; + private final FirebaseMessagingPort firebasePort; + + @Override + public void handleFollower(final FeedEvents.FollowerEvent event) { + Notification n = buildNotification("ํŒ”๋กœ์›Œ ์•Œ๋ฆผ", + "@" + event.actorUsername() + " ๋‹˜์ด ๋‚˜๋ฅผ ๋ฑํ–ˆ์–ด์š”!"); + + List tokens = fcmTokenLoadPort.findEnabledByUserId(event.targetUserId()); + + if (tokens.isEmpty()) return; + + List msgs = new ArrayList<>(tokens.size()); + List tk = new ArrayList<>(tokens.size()); + List dev = new ArrayList<>(tokens.size()); + + for (FcmToken t : tokens) { + Message m = buildMessage(t.getFcmToken(), n, + MessageRoute.FEED_USER, + "userId", String.valueOf(event.actorUserId())); + + msgs.add(m); tk.add(t.getFcmToken()); dev.add(t.getDeviceId()); + } + firebasePort.sendBatch(msgs, tk, dev); + } + + @Override + public void handleFeedCommented(final FeedEvents.FeedCommentedEvent event) { + Notification notification = buildNotification("์ƒˆ๋กœ์šด ๋Œ“๊ธ€์ด ๋‹ฌ๋ ธ์–ด์š”", + "@" +event.actorUsername() + " ๋‹˜์ด ๋‚ด ๊ธ€์— ๋Œ“๊ธ€์„ ๋‹ฌ์•˜์–ด์š”!"); + + pushFeedDetail(event.targetUserId(), notification, event.feedId()); + } + + @Override + public void handleFeedReplied(final FeedEvents.FeedRepliedEvent event) { + Notification notification = buildNotification("์ƒˆ๋กœ์šด ๋‹ต๊ธ€์ด ๋‹ฌ๋ ธ์–ด์š”", + "@" + event.actorUsername() + " ๋‹˜์ด ๋‚ด ๋Œ“๊ธ€์— ๋‹ต๊ธ€์„ ๋‹ฌ์•˜์–ด์š”!"); + + pushFeedDetail(event.targetUserId(), notification, event.feedId()); + } + + @Override + public void handleFolloweeNewPost(final FeedEvents.FolloweeNewPostEvent event) { + Notification notification = buildNotification("์ƒˆ ๊ธ€ ์•Œ๋ฆผ", + "@" + event.actorUsername() + " ๋‹˜์ด ์ƒˆ๋กœ์šด ๊ธ€์„ ์ž‘์„ฑํ–ˆ์–ด์š”!"); + + pushFeedDetail(event.targetUserId(), notification, event.feedId()); + } + + @Override + public void handleFeedLiked(final FeedEvents.FeedLikedEvent event) { + Notification notification = buildNotification("๋‚ด ๊ธ€์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค", + "@" + event.actorUsername() + " ๋‹˜์ด ๋‚ด ๊ธ€์— ์ข‹์•„์š”๋ฅผ ๋ˆŒ๋ €์–ด์š”!"); + + pushFeedDetail(event.targetUserId(), notification, event.feedId()); + } + + @Override + public void handleFeedCommentLiked(final FeedEvents.FeedCommentLikedEvent event) { + Notification notification = buildNotification("์ข‹์•„์š” ์•Œ๋ฆผ", + "@" + event.actorUsername() + " ๋‹˜์ด ๋‚ด ๋Œ“๊ธ€์— ์ข‹์•„์š”๋ฅผ ๋ˆŒ๋ €์–ด์š”!"); + + pushFeedDetail(event.targetUserId(), notification, event.feedId()); + } + + private void pushFeedDetail(Long userId, Notification notification, Long feedId) { + List tokens = fcmTokenLoadPort.findEnabledByUserId(userId); + + if (tokens.isEmpty()) return; + + List msgs = new ArrayList<>(tokens.size()); + List tk = new ArrayList<>(tokens.size()); + List dev = new ArrayList<>(tokens.size()); + + for (FcmToken t : tokens) { + Message m = buildMessage(t.getFcmToken(), notification, + MessageRoute.FEED_DETAIL, + "feedId", String.valueOf(feedId)); + + msgs.add(m); + tk.add(t.getFcmToken()); + dev.add(t.getDeviceId()); + } + firebasePort.sendBatch(msgs, tk, dev); + } + + private Notification buildNotification(final String title, final String body) { + return Notification.builder().setTitle(NotificationCategory.FEED.prefixedTitle(title)).setBody(body).build(); + } + + private Message buildMessage(final String token, final Notification n, + final MessageRoute route, + final String... kv) { + Message.Builder b = Message.builder() + .setToken(token) + .setNotification(n) + .putData("category", NotificationCategory.FEED.getDisplay()) + .putData("action", "OPEN_ROUTE") + .putData("route", route.getCode()); + for (int i = 0; i + 1 < kv.length; i += 2) b.putData(kv[i], kv[i + 1]); + return b.build(); + } +} \ No newline at end of file diff --git a/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java b/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java new file mode 100644 index 000000000..09e83770e --- /dev/null +++ b/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java @@ -0,0 +1,235 @@ +package konkuk.thip.message.application.service; + +import com.google.firebase.messaging.Message; +import com.google.firebase.messaging.Notification; +import konkuk.thip.message.application.port.in.RoomNotificationDispatchUseCase; +import konkuk.thip.message.application.port.out.FirebaseMessagingPort; +import konkuk.thip.message.adapter.out.event.dto.RoomEvents; +import konkuk.thip.message.domain.NotificationCategory; +import konkuk.thip.message.domain.MessageRoute; +import konkuk.thip.notification.application.port.out.FcmTokenLoadPort; +import konkuk.thip.notification.domain.FcmToken; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class RoomNotificationDispatchService implements RoomNotificationDispatchUseCase { + + private final FcmTokenLoadPort fcmTokenQueryPort; + private final FirebaseMessagingPort firebasePort; + + @Override + public void handleRoomRecordCommented(final RoomEvents.RoomRecordCommentedEvent event) { + Notification notification = buildNotification("์ƒˆ๋กœ์šด ๋Œ“๊ธ€์ด ๋‹ฌ๋ ธ์–ด์š”", + "@" + event.actorUsername() + " ๋‹˜์ด ๋‚ด ๋…์„œ๊ธฐ๋ก์— ๋Œ“๊ธ€์„ ๋‹ฌ์•˜์–ด์š”!"); + + List tokens = fcmTokenQueryPort.findEnabledByUserId(event.targetUserId()); + if (tokens.isEmpty()) return; + + List msgs = new ArrayList<>(tokens.size()); + List tk = new ArrayList<>(tokens.size()); + List dev = new ArrayList<>(tokens.size()); + + for (FcmToken t : tokens) { + Message m = buildMessage(t.getFcmToken(), notification, + MessageRoute.ROOM_RECORD_DETAIL, + "roomId", String.valueOf(event.roomId()), + "page", String.valueOf(event.page()), + "type", "group", + "postId", String.valueOf(event.postId()), + "postType", event.postType()); + + msgs.add(m); tk.add(t.getFcmToken()); dev.add(t.getDeviceId()); + } + firebasePort.sendBatch(msgs, tk, dev); + } + + @Override + public void handleRoomVoteStarted(final RoomEvents.RoomVoteStartedEvent event) { + Notification notification = buildNotification(event.roomTitle(), + "์ƒˆ๋กœ์šด ํˆฌํ‘œ๊ฐ€ ์‹œ์ž‘๋˜์—ˆ์–ด์š”!"); + + List tokens = fcmTokenQueryPort.findEnabledByUserId(event.targetUserId()); + if (tokens.isEmpty()) return; + + List msgs = new ArrayList<>(tokens.size()); + List tk = new ArrayList<>(tokens.size()); + List dev = new ArrayList<>(tokens.size()); + + for (FcmToken t : tokens) { + Message m = buildMessage(t.getFcmToken(), notification, + MessageRoute.ROOM_VOTE_DETAIL, + "roomId", String.valueOf(event.roomId()), + "page", String.valueOf(event.page()), + "type", "group", + "postId", String.valueOf(event.postId()), + "postType", "VOTE"); + + msgs.add(m); tk.add(t.getFcmToken()); dev.add(t.getDeviceId()); + } + firebasePort.sendBatch(msgs, tk, dev); + } + + @Override + public void handleRoomRecordCreated(final RoomEvents.RoomRecordCreatedEvent event) { + Notification notification = buildNotification(event.roomTitle(), + "@" + event.actorUsername() + " ๋‹˜์ด ์ƒˆ๋กœ์šด ๋…์„œ ๊ธฐ๋ก์„ ์ž‘์„ฑํ–ˆ์–ด์š”!"); + + List tokens = fcmTokenQueryPort.findEnabledByUserId(event.targetUserId()); + if (tokens.isEmpty()) return; + + List msgs = new ArrayList<>(tokens.size()); + List tk = new ArrayList<>(tokens.size()); + List dev = new ArrayList<>(tokens.size()); + + for (FcmToken t : tokens) { + Message m = buildMessage(t.getFcmToken(), notification, + MessageRoute.ROOM_RECORD_DETAIL, + "roomId", String.valueOf(event.roomId()), + "page", String.valueOf(event.page()), + "type", "group", + "postId", String.valueOf(event.postId()), + "postType", "RECORD"); + + msgs.add(m); tk.add(t.getFcmToken()); dev.add(t.getDeviceId()); + } + firebasePort.sendBatch(msgs, tk, dev); + } + + @Override + public void handleRoomRecruitClosedEarly(final RoomEvents.RoomRecruitClosedEarlyEvent event) { + Notification n = buildNotification(event.roomTitle(), + "๋ชจ์ž„๋ฐฉ ํ™œ๋™์ด ์‹œ์ž‘๋˜์—ˆ์–ด์š”. ๋ชจ์ž„๋ฐฉ์—์„œ ๋…์„œ ๊ธฐ๋ก์„ ์‹œ์ž‘ํ•ด๋ณด์„ธ์š”!"); + + pushRoomMain(event.targetUserId(), event.roomId(), n); + } + + @Override + public void handleRoomActivityStarted(final RoomEvents.RoomActivityStartedEvent event) { + Notification notification = buildNotification(event.roomTitle(), + "๋ชจ์ž„๋ฐฉ ํ™œ๋™์ด ์‹œ์ž‘๋˜์—ˆ์–ด์š”. ๋ชจ์ž„๋ฐฉ์—์„œ ๋…์„œ ๊ธฐ๋ก์„ ์‹œ์ž‘ํ•ด๋ณด์„ธ์š”!"); + + pushRoomMain(event.targetUserId(), event.roomId(), notification); + } + + @Override + public void handleRoomJoinRequestedToOwner(final RoomEvents.RoomJoinRequestedToOwnerEvent event) { + Notification n = buildNotification(event.roomTitle(), + "@" + event.applicantUsername() + " ๋‹˜์ด ๋ชจ์ž„์— ์ฐธ์—ฌํ–ˆ์–ด์š”!"); + + pushRoomDetail(event.ownerUserId(), event.roomId(), n); + } + + @Override + public void handleRoomCommentLiked(final RoomEvents.RoomCommentLikedEvent event) { + Notification notification = buildNotification("๋‚ด ๋Œ“๊ธ€์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค", + "@" + event.actorUsername() + " ๋‹˜์ด ๋‚ด ๋Œ“๊ธ€์— ์ข‹์•„์š”๋ฅผ ๋ˆŒ๋ €์–ด์š”!"); + + List tokens = fcmTokenQueryPort.findEnabledByUserId(event.targetUserId()); + if (tokens.isEmpty()) return; + + List msgs = new ArrayList<>(tokens.size()); + List tk = new ArrayList<>(tokens.size()); + List dev = new ArrayList<>(tokens.size()); + + for (FcmToken t : tokens) { + Message m = buildMessage(t.getFcmToken(), notification, + MessageRoute.ROOM_RECORD_DETAIL, + "roomId", String.valueOf(event.roomId()), + "page", String.valueOf(event.page()), + "type", "group", + "postId", String.valueOf(event.postId()), + "postType", "RECORD"); + msgs.add(m); tk.add(t.getFcmToken()); dev.add(t.getDeviceId()); + } + firebasePort.sendBatch(msgs, tk, dev); + } + + @Override + public void handleRoomRecordLiked(final RoomEvents.RoomRecordLikedEvent event) { + Notification notification = buildNotification("์ข‹์•„์š” ์•Œ๋ฆผ", + "@" + event.actorUsername() + " ๋‹˜์ด ๋‚ด ๋…์„œ๊ธฐ๋ก์— ์ข‹์•„์š”๋ฅผ ๋ˆŒ๋ €์–ด์š”!"); + + List tokens = fcmTokenQueryPort.findEnabledByUserId(event.targetUserId()); + if (tokens.isEmpty()) return; + + List msgs = new ArrayList<>(tokens.size()); + List tk = new ArrayList<>(tokens.size()); + List dev = new ArrayList<>(tokens.size()); + + for (FcmToken t : tokens) { + Message m = buildMessage(t.getFcmToken(), notification, + MessageRoute.ROOM_RECORD_DETAIL, + "roomId", String.valueOf(event.roomId()), + "page", String.valueOf(event.page()), + "type", "group", + "postId", String.valueOf(event.postId()), + "postType", "RECORD"); + msgs.add(m); tk.add(t.getFcmToken()); dev.add(t.getDeviceId()); + } + firebasePort.sendBatch(msgs, tk, dev); + } + + // ===== helpers ===== + + private void pushRoomMain(Long targetUserId, Long roomId, Notification notification) { + List tokens = fcmTokenQueryPort.findEnabledByUserId(targetUserId); + + if (tokens.isEmpty()) return; + + List msgs = new ArrayList<>(tokens.size()); + List tk = new ArrayList<>(tokens.size()); + List dev = new ArrayList<>(tokens.size()); + + for (FcmToken t : tokens) { + Message m = buildMessage(t.getFcmToken(), notification, + MessageRoute.ROOM_MAIN, + "roomId", String.valueOf(roomId)); + + msgs.add(m); tk.add(t.getFcmToken()); dev.add(t.getDeviceId()); + } + firebasePort.sendBatch(msgs, tk, dev); + } + + private void pushRoomDetail(Long targetUserId, Long roomId, Notification notification) { + List tokens = fcmTokenQueryPort.findEnabledByUserId(targetUserId); + + if (tokens.isEmpty()) return; + + List msgs = new ArrayList<>(tokens.size()); + List tk = new ArrayList<>(tokens.size()); + List dev = new ArrayList<>(tokens.size()); + + for (FcmToken t : tokens) { + Message m = buildMessage(t.getFcmToken(), notification, + MessageRoute.ROOM_DETAIL, + "roomId", String.valueOf(roomId)); + + msgs.add(m); tk.add(t.getFcmToken()); dev.add(t.getDeviceId()); + } + firebasePort.sendBatch(msgs, tk, dev); + } + + private Notification buildNotification(final String title, final String body) { + return Notification.builder().setTitle(NotificationCategory.ROOM.prefixedTitle(title)).setBody(body).build(); + } + + private Message buildMessage(final String token, final Notification n, + final MessageRoute route, + final String... kv) { + var b = Message.builder() + .setToken(token) + .setNotification(n) + .putData("category", NotificationCategory.ROOM.getDisplay()) + .putData("action", "OPEN_ROUTE") + .putData("route", route.getCode()); + for (int i = 0; i + 1 < kv.length; i += 2) b.putData(kv[i], kv[i + 1]); + return b.build(); + } +} \ No newline at end of file From 7d38012458ce5ce5647236fd98b6cd8f24d7a95b Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 4 Sep 2025 18:33:35 +0900 Subject: [PATCH 28/93] =?UTF-8?q?[feat]=20Firebase=20Adapater=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../out/firebase/FakeFirebaseAdapter.java | 26 ++++++++++ .../adapter/out/firebase/FirebaseAdapter.java | 48 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 src/main/java/konkuk/thip/message/adapter/out/firebase/FakeFirebaseAdapter.java create mode 100644 src/main/java/konkuk/thip/message/adapter/out/firebase/FirebaseAdapter.java diff --git a/src/main/java/konkuk/thip/message/adapter/out/firebase/FakeFirebaseAdapter.java b/src/main/java/konkuk/thip/message/adapter/out/firebase/FakeFirebaseAdapter.java new file mode 100644 index 000000000..19e7204d1 --- /dev/null +++ b/src/main/java/konkuk/thip/message/adapter/out/firebase/FakeFirebaseAdapter.java @@ -0,0 +1,26 @@ +package konkuk.thip.message.adapter.out.firebase; + +import com.google.firebase.messaging.Message; +import konkuk.thip.message.application.port.out.FirebaseMessagingPort; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Slf4j +@Component +@Profile("local | test") +@RequiredArgsConstructor +public class FakeFirebaseAdapter implements FirebaseMessagingPort { + @Override + public void send(Message message, String fcmToken, String deviceId) { + log.info("FirebaseAdapter.send()"); + } + + @Override + public void sendBatch(List messages, List fcmTokens, List deviceIds) { + log.info("FirebaseAdapter.sendBatch()"); + } +} diff --git a/src/main/java/konkuk/thip/message/adapter/out/firebase/FirebaseAdapter.java b/src/main/java/konkuk/thip/message/adapter/out/firebase/FirebaseAdapter.java new file mode 100644 index 000000000..b33fa45ab --- /dev/null +++ b/src/main/java/konkuk/thip/message/adapter/out/firebase/FirebaseAdapter.java @@ -0,0 +1,48 @@ +package konkuk.thip.message.adapter.out.firebase; + +import com.google.firebase.messaging.*; +import konkuk.thip.common.exception.FirebaseException; +import konkuk.thip.message.application.port.out.FirebaseMessagingPort; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Slf4j +@Component +@Profile("prod | dev") +@RequiredArgsConstructor +public class FirebaseAdapter implements FirebaseMessagingPort { + + private final FirebaseMessaging firebaseMessaging; + + @Override + public void send(Message message, String fcmToken, String deviceId) { + try { + firebaseMessaging.send(message); + } catch (FirebaseMessagingException e) { + throw new FirebaseException(e); + } + } + + @Override + public void sendBatch(List messages, List fcmTokens, List deviceIds) { + if (messages.size() != fcmTokens.size() || messages.size() != deviceIds.size()) { + throw new FirebaseException(new IllegalArgumentException("๋ฉ”์‹œ์ง€, FCM ํ† ํฐ, ๋””๋ฐ”์ด์Šค ID ๋ฆฌ์ŠคํŠธ์˜ ํฌ๊ธฐ๋Š” ๊ฐ™์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.")); + } + + try { + BatchResponse batchResponse = firebaseMessaging.sendEach(messages); + + if (batchResponse.getFailureCount() > 0) { + log.warn("[FCM:BATCH] ์ผ๋ถ€ ๋ฉ”์‹œ์ง€ ์ „์†ก ์‹คํŒจ: {}/{}", batchResponse.getFailureCount(), messages.size()); + throw new FirebaseException(); + } + } catch (FirebaseMessagingException e) { + log.warn("[FCM:BATCH] ๋ฉ”์‹œ์ง€ ์ „์†ก ์‹คํŒจ: {}", e.getMessage()); + throw new FirebaseException(e); + } + } +} From 9ebe0672234826545429226383903b6684de8ffe Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 4 Sep 2025 18:33:49 +0900 Subject: [PATCH 29/93] =?UTF-8?q?[feat]=20=ED=95=84=EC=9A=94=ED=95=9C=20?= =?UTF-8?q?=EC=97=90=EB=9F=AC=20=EC=A0=95=EC=9D=98=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/exception/FirebaseException.java | 21 +++++++++++++++++++ .../thip/common/exception/code/ErrorCode.java | 1 + 2 files changed, 22 insertions(+) create mode 100644 src/main/java/konkuk/thip/common/exception/FirebaseException.java diff --git a/src/main/java/konkuk/thip/common/exception/FirebaseException.java b/src/main/java/konkuk/thip/common/exception/FirebaseException.java new file mode 100644 index 000000000..a4d97a046 --- /dev/null +++ b/src/main/java/konkuk/thip/common/exception/FirebaseException.java @@ -0,0 +1,21 @@ +package konkuk.thip.common.exception; + +import konkuk.thip.common.exception.code.ErrorCode; + +public class FirebaseException extends BusinessException { + public FirebaseException(ErrorCode errorCode) { + super(errorCode); + } + + public FirebaseException(ErrorCode errorCode, Exception e) { + super(errorCode, e); + } + + public FirebaseException(Exception e) { + super(ErrorCode.FIREBASE_SEND_ERROR, e); + } + + public FirebaseException() { + super(ErrorCode.FIREBASE_SEND_ERROR); + } +} diff --git a/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java b/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java index 0b608689a..6832186ce 100644 --- a/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java +++ b/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java @@ -216,6 +216,7 @@ public enum ErrorCode implements ResponseCode { */ FCM_TOKEN_NOT_FOUND(HttpStatus.NOT_FOUND, 200000, "์กด์žฌํ•˜์ง€ ์•Š๋Š” FCM TOKEN ์ž…๋‹ˆ๋‹ค."), FCM_TOKEN_ENABLED_STATE_ALREADY(HttpStatus.BAD_REQUEST, 200001, "์š”์ฒญํ•œ ์ƒํƒœ๋กœ ์ด๋ฏธ ํ‘ธ์‰ฌ์•Œ๋ฆผ ์—ฌ๋ถ€๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค."), + FIREBASE_SEND_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 200003, "FCM ํ‘ธ์‰ฌ์•Œ๋ฆผ ์ „์†ก์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.") ; From fecad55a90330b4d833944fbeea37e19861ae66a Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 4 Sep 2025 18:34:10 +0900 Subject: [PATCH 30/93] =?UTF-8?q?[feat]=20=ED=91=B8=EC=89=AC=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EC=B9=B4=ED=85=8C=EA=B3=A0=EB=A6=AC=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../port/out/FirebaseMessagingPort.java | 11 +++++++++++ .../message/domain/NotificationCategory.java | 17 +++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/main/java/konkuk/thip/message/application/port/out/FirebaseMessagingPort.java create mode 100644 src/main/java/konkuk/thip/message/domain/NotificationCategory.java diff --git a/src/main/java/konkuk/thip/message/application/port/out/FirebaseMessagingPort.java b/src/main/java/konkuk/thip/message/application/port/out/FirebaseMessagingPort.java new file mode 100644 index 000000000..f0acd88ee --- /dev/null +++ b/src/main/java/konkuk/thip/message/application/port/out/FirebaseMessagingPort.java @@ -0,0 +1,11 @@ +package konkuk.thip.message.application.port.out; + +import com.google.firebase.messaging.Message; + +import java.util.List; + +public interface FirebaseMessagingPort { + void send(Message message, String fcmToken, String deviceId); + + void sendBatch(List messages, List fcmTokens, List deviceIds); +} diff --git a/src/main/java/konkuk/thip/message/domain/NotificationCategory.java b/src/main/java/konkuk/thip/message/domain/NotificationCategory.java new file mode 100644 index 000000000..3280395a2 --- /dev/null +++ b/src/main/java/konkuk/thip/message/domain/NotificationCategory.java @@ -0,0 +1,17 @@ +package konkuk.thip.message.domain; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum NotificationCategory { + FEED("ํ”ผ๋“œ"), + ROOM("๋ชจ์ž„"); + + private final String display; + + public String prefixedTitle(String title) { + return "[" + display + "] " + title; + } +} \ No newline at end of file From 390ad6048960cdbf86c9c2fac3cca136ac273935 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 4 Sep 2025 18:34:23 +0900 Subject: [PATCH 31/93] =?UTF-8?q?[feat]=20=ED=99=94=EB=A9=B4=20=EB=82=B4?= =?UTF-8?q?=EB=B9=84=EA=B2=8C=EC=9D=B4=EC=85=98=20=EB=9D=BC=EC=9A=B0?= =?UTF-8?q?=ED=8A=B8=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/message/domain/MessageRoute.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/main/java/konkuk/thip/message/domain/MessageRoute.java diff --git a/src/main/java/konkuk/thip/message/domain/MessageRoute.java b/src/main/java/konkuk/thip/message/domain/MessageRoute.java new file mode 100644 index 000000000..457aaa924 --- /dev/null +++ b/src/main/java/konkuk/thip/message/domain/MessageRoute.java @@ -0,0 +1,20 @@ +package konkuk.thip.message.domain; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum MessageRoute { + // FEED + FEED_USER("FEED_USER"), // ์ž์‹ ์„ ํŒ”๋กœ์šฐํ•œ ์‚ฌ์šฉ์ž์˜ ํ”ผ๋“œ ๋ชฉ๋ก์œผ๋กœ ํ™”๋ฉด ์ด๋™ + FEED_DETAIL("FEED_DETAIL"), // ํŠน์ • ํ”ผ๋“œ ์ƒ์„ธ ํ™”๋ฉด์œผ๋กœ ์ด๋™ + + // ROOM + ROOM_MAIN("ROOM_MAIN"), // ํŠน์ • ๋ชจ์ž„๋ฐฉ ๋ฉ”์ธ ํ™”๋ฉด์œผ๋กœ ์ด๋™ + ROOM_DETAIL("ROOM_DETAIL"), // ํŠน์ • ๋ชจ์ž„ ์ƒ์„ธ์ •๋ณด ํ™”๋ฉด์œผ๋กœ ์ด๋™ + ROOM_RECORD_DETAIL("ROOM_RECORD_DETAIL"), // ํŠน์ • ๋ชจ์ž„ ๊ธฐ๋ก ์ƒ์„ธ ํ™”๋ฉด์œผ๋กœ ์ด๋™ (๊ธฐ๋ก์žฅ ์กฐํšŒ - ํŽ˜์ด์ง€ ํ•„ํ„ฐ ๊ฑธ๋ฆฐ์ฑ„๋กœ) + ROOM_VOTE_DETAIL("ROOM_VOTE_DETAIL"); // ํŠน์ • ๋ชจ์ž„ ํˆฌํ‘œ ์ƒ์„ธ ํ™”๋ฉด์œผ๋กœ ์ด๋™ (ํˆฌํ‘œ ์กฐํšŒ - ํŽ˜์ด์ง€ ํ•„ํ„ฐ ๊ฑธ๋ฆฐ์ฑ„๋กœ) + + private final String code; +} \ No newline at end of file From 01eb5aff113efc1e3e2cf953903be1a681e2b4b7 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 4 Sep 2025 18:34:47 +0900 Subject: [PATCH 32/93] =?UTF-8?q?[docs]=20=EC=8A=A4=EC=9B=A8=EA=B1=B0=20?= =?UTF-8?q?=EB=AA=85=EC=84=B8=20=EC=88=98=EC=A0=95=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/in/web/NotificationCommandController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java b/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java index 8121bd0be..b7e7c8481 100644 --- a/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java +++ b/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java @@ -28,7 +28,7 @@ public class NotificationCommandController { private final FcmEnableStateChangeUseCase fcmEnableStateChangeUseCase; private final FcmDeleteUseCase fcmDeleteUseCase; - @Operation(summary = "FCM ํ† ํฐ ๋“ฑ๋ก", description = "์‚ฌ์šฉ์ž์˜ FCM ํ† ํฐ์„ ์„œ๋ฒ„์— ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด ํ† ํฐ์ด ์žˆ๋‹ค๋ฉด userId+deviceId ๊ธฐ์ค€์œผ๋กœ ํ† ํฐ์„ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค.") + @Operation(summary = "FCM ํ† ํฐ ๋“ฑ๋ก", description = "์‚ฌ์šฉ์ž์˜ FCM ํ† ํฐ์„ ์„œ๋ฒ„์— ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด ํ† ํฐ์ด ์žˆ๋‹ค๋ฉด deviceId ๊ธฐ์ค€์œผ๋กœ ํ† ํฐ์„ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค.") @PostMapping("/fcm-tokens") @ExceptionDescription(FCM_TOKEN_REGISTER) public BaseResponse registerFcmToken( From b663c7b9b7e939a2ab950cf2f7e74a737e80e938 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 4 Sep 2025 19:17:41 +0900 Subject: [PATCH 33/93] =?UTF-8?q?[refactor]=20=EC=95=A0=EB=A7=A4=ED=95=9C?= =?UTF-8?q?=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/in/event/MessageFeedEventListener.java | 4 ++-- .../adapter/in/event/MessageRoomEventListener.java | 10 ++++++++-- .../adapter/out/event/FeedEventPublisherAdapter.java | 2 +- .../thip/message/adapter/out/event/dto/FeedEvents.java | 4 ++-- .../port/in/FeedNotificationDispatchUseCase.java | 2 +- .../service/FeedNotificationDispatchService.java | 2 +- 6 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/main/java/konkuk/thip/message/adapter/in/event/MessageFeedEventListener.java b/src/main/java/konkuk/thip/message/adapter/in/event/MessageFeedEventListener.java index b3087a7cf..0046465e2 100644 --- a/src/main/java/konkuk/thip/message/adapter/in/event/MessageFeedEventListener.java +++ b/src/main/java/konkuk/thip/message/adapter/in/event/MessageFeedEventListener.java @@ -29,8 +29,8 @@ public void onFeedCommented(FeedEvents.FeedCommentedEvent e) { @Async @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) - public void onFeedReplied(FeedEvents.FeedRepliedEvent e) { - feedUseCase.handleFeedReplied(e); + public void onFeedCommentReplied(FeedEvents.FeedCommentRepliedEvent e) { + feedUseCase.handleFeedCommentReplied(e); } @Async diff --git a/src/main/java/konkuk/thip/message/adapter/in/event/MessageRoomEventListener.java b/src/main/java/konkuk/thip/message/adapter/in/event/MessageRoomEventListener.java index dd747fe46..ba30601a9 100644 --- a/src/main/java/konkuk/thip/message/adapter/in/event/MessageRoomEventListener.java +++ b/src/main/java/konkuk/thip/message/adapter/in/event/MessageRoomEventListener.java @@ -16,7 +16,7 @@ public class MessageRoomEventListener { @Async @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) - public void onRoomRecordCommented(RoomEvents.RoomRecordCommentedEvent e) { + public void onRoomPostCommented(RoomEvents.RoomPostCommentedEvent e) { roomUseCase.handleRoomRecordCommented(e); } @@ -58,7 +58,13 @@ public void onRoomCommentLiked(RoomEvents.RoomCommentLikedEvent e) { @Async @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) - public void onRoomRecordLiked(RoomEvents.RoomRecordLikedEvent e) { + public void onRoomPostLiked(RoomEvents.RoomPostLikedEvent e) { roomUseCase.handleRoomRecordLiked(e); } + + @Async + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void onRoomPostCommentReplied(RoomEvents.RoomPostCommentRepliedEvent e) { + roomUseCase.handleRoomRecordCommentReplied(e); + } } diff --git a/src/main/java/konkuk/thip/message/adapter/out/event/FeedEventPublisherAdapter.java b/src/main/java/konkuk/thip/message/adapter/out/event/FeedEventPublisherAdapter.java index 285fc7008..b826b181e 100644 --- a/src/main/java/konkuk/thip/message/adapter/out/event/FeedEventPublisherAdapter.java +++ b/src/main/java/konkuk/thip/message/adapter/out/event/FeedEventPublisherAdapter.java @@ -35,7 +35,7 @@ public void publishFeedCommentedEvent(Long targetUserId, Long actorUserId, Strin @Override public void publishFeedRepliedEvent(Long targetUserId, Long actorUserId, String actorUsername, Long feedId) { - publisher.publishEvent(FeedEvents.FeedRepliedEvent.builder() + publisher.publishEvent(FeedEvents.FeedCommentRepliedEvent.builder() .targetUserId(targetUserId) .actorUserId(actorUserId) .actorUsername(actorUsername) diff --git a/src/main/java/konkuk/thip/message/adapter/out/event/dto/FeedEvents.java b/src/main/java/konkuk/thip/message/adapter/out/event/dto/FeedEvents.java index c687bd6c2..176f1f801 100644 --- a/src/main/java/konkuk/thip/message/adapter/out/event/dto/FeedEvents.java +++ b/src/main/java/konkuk/thip/message/adapter/out/event/dto/FeedEvents.java @@ -16,8 +16,8 @@ public record FeedCommentedEvent(Long targetUserId, Long actorUserId, String act // ๋ˆ„๊ตฐ๊ฐ€ ๋‚ด ๋Œ“๊ธ€์— ๋Œ€๋Œ“๊ธ€์„ ๋‹ค๋Š” ๊ฒฝ์šฐ @Builder - public record FeedRepliedEvent(Long targetUserId, Long actorUserId, String actorUsername, - Long feedId) {} + public record FeedCommentRepliedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long feedId) {} // ๋‚ด๊ฐ€ ํŒ”๋กœ์šฐํ•˜๋Š” ์‚ฌ๋žŒ์ด ์ƒˆ ๊ธ€์„ ์˜ฌ๋ฆฌ๋Š” ๊ฒฝ์šฐ @Builder diff --git a/src/main/java/konkuk/thip/message/application/port/in/FeedNotificationDispatchUseCase.java b/src/main/java/konkuk/thip/message/application/port/in/FeedNotificationDispatchUseCase.java index eba755db3..66eaee3e8 100644 --- a/src/main/java/konkuk/thip/message/application/port/in/FeedNotificationDispatchUseCase.java +++ b/src/main/java/konkuk/thip/message/application/port/in/FeedNotificationDispatchUseCase.java @@ -7,7 +7,7 @@ public interface FeedNotificationDispatchUseCase { void handleFeedCommented(FeedEvents.FeedCommentedEvent e); - void handleFeedReplied(FeedEvents.FeedRepliedEvent e); + void handleFeedCommentReplied(FeedEvents.FeedCommentRepliedEvent e); void handleFolloweeNewPost(FeedEvents.FolloweeNewPostEvent e); diff --git a/src/main/java/konkuk/thip/message/application/service/FeedNotificationDispatchService.java b/src/main/java/konkuk/thip/message/application/service/FeedNotificationDispatchService.java index 20e9956ee..2ae8c9ad1 100644 --- a/src/main/java/konkuk/thip/message/application/service/FeedNotificationDispatchService.java +++ b/src/main/java/konkuk/thip/message/application/service/FeedNotificationDispatchService.java @@ -56,7 +56,7 @@ public void handleFeedCommented(final FeedEvents.FeedCommentedEvent event) { } @Override - public void handleFeedReplied(final FeedEvents.FeedRepliedEvent event) { + public void handleFeedCommentReplied(final FeedEvents.FeedCommentRepliedEvent event) { Notification notification = buildNotification("์ƒˆ๋กœ์šด ๋‹ต๊ธ€์ด ๋‹ฌ๋ ธ์–ด์š”", "@" + event.actorUsername() + " ๋‹˜์ด ๋‚ด ๋Œ“๊ธ€์— ๋‹ต๊ธ€์„ ๋‹ฌ์•˜์–ด์š”!"); From 0c433e01d7659c8d90e5ff1395cbfba7dd534c72 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Thu, 4 Sep 2025 19:19:18 +0900 Subject: [PATCH 34/93] =?UTF-8?q?[refactor]=20=EC=95=A0=EB=A7=A4=ED=95=9C?= =?UTF-8?q?=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20+=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BC=80=EC=9D=B4=EC=8A=A4=20=EC=B6=94=EA=B0=80=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../in/event/MessageRoomEventListener.java | 6 ++-- .../out/event/RoomEventPublisherAdapter.java | 25 ++++++++++++---- .../adapter/out/event/dto/RoomEvents.java | 11 +++++-- .../in/RoomNotificationDispatchUseCase.java | 6 ++-- .../port/out/RoomEventCommandPort.java | 11 ++++--- .../RoomNotificationDispatchService.java | 30 +++++++++++++++++-- 6 files changed, 69 insertions(+), 20 deletions(-) diff --git a/src/main/java/konkuk/thip/message/adapter/in/event/MessageRoomEventListener.java b/src/main/java/konkuk/thip/message/adapter/in/event/MessageRoomEventListener.java index ba30601a9..7582dbaa3 100644 --- a/src/main/java/konkuk/thip/message/adapter/in/event/MessageRoomEventListener.java +++ b/src/main/java/konkuk/thip/message/adapter/in/event/MessageRoomEventListener.java @@ -17,7 +17,7 @@ public class MessageRoomEventListener { @Async @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) public void onRoomPostCommented(RoomEvents.RoomPostCommentedEvent e) { - roomUseCase.handleRoomRecordCommented(e); + roomUseCase.handleRoomPostCommented(e); } @Async @@ -59,12 +59,12 @@ public void onRoomCommentLiked(RoomEvents.RoomCommentLikedEvent e) { @Async @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) public void onRoomPostLiked(RoomEvents.RoomPostLikedEvent e) { - roomUseCase.handleRoomRecordLiked(e); + roomUseCase.handleRoomPostLiked(e); } @Async @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) public void onRoomPostCommentReplied(RoomEvents.RoomPostCommentRepliedEvent e) { - roomUseCase.handleRoomRecordCommentReplied(e); + roomUseCase.handleRoomPostCommentReplied(e); } } diff --git a/src/main/java/konkuk/thip/message/adapter/out/event/RoomEventPublisherAdapter.java b/src/main/java/konkuk/thip/message/adapter/out/event/RoomEventPublisherAdapter.java index 8d2620b2b..8c46e60f3 100644 --- a/src/main/java/konkuk/thip/message/adapter/out/event/RoomEventPublisherAdapter.java +++ b/src/main/java/konkuk/thip/message/adapter/out/event/RoomEventPublisherAdapter.java @@ -13,9 +13,9 @@ public class RoomEventPublisherAdapter implements RoomEventCommandPort { private final ApplicationEventPublisher publisher; @Override - public void publishRoomRecordCommentedEvent(Long targetUserId, Long actorUserId, String actorUsername, - Long roomId, Integer page, Long postId, String postType) { - publisher.publishEvent(RoomEvents.RoomRecordCommentedEvent.builder() + public void publishRoomPostCommentedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long roomId, Integer page, Long postId, String postType) { + publisher.publishEvent(RoomEvents.RoomPostCommentedEvent.builder() .targetUserId(targetUserId) .actorUserId(actorUserId) .actorUsername(actorUsername) @@ -96,9 +96,22 @@ public void publishRoomCommentLikedEvent(Long targetUserId, Long actorUserId, St } @Override - public void publishRoomRecordLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, - Long roomId, Integer page, Long postId, String postType) { - publisher.publishEvent(RoomEvents.RoomRecordLikedEvent.builder() + public void publishRoomPostLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long roomId, Integer page, Long postId, String postType) { + publisher.publishEvent(RoomEvents.RoomPostLikedEvent.builder() + .targetUserId(targetUserId) + .actorUserId(actorUserId) + .actorUsername(actorUsername) + .roomId(roomId) + .page(page) + .postId(postId) + .postType(postType) + .build()); + } + + @Override + public void publicRoomPostCommentRepliedEvent(Long targetUserId, Long actorUserId, String actorUsername, Long roomId, Integer page, Long postId, String postType) { + publisher.publishEvent(RoomEvents.RoomPostCommentRepliedEvent.builder() .targetUserId(targetUserId) .actorUserId(actorUserId) .actorUsername(actorUsername) diff --git a/src/main/java/konkuk/thip/message/adapter/out/event/dto/RoomEvents.java b/src/main/java/konkuk/thip/message/adapter/out/event/dto/RoomEvents.java index 1cd43bfc7..4aa6cc66d 100644 --- a/src/main/java/konkuk/thip/message/adapter/out/event/dto/RoomEvents.java +++ b/src/main/java/konkuk/thip/message/adapter/out/event/dto/RoomEvents.java @@ -8,8 +8,8 @@ public class RoomEvents { // ๋Œ“๊ธ€ ๋Œ€์ƒ์ด "๊ธฐ๋ก/ํˆฌํ‘œ" ๋ชจ๋‘ ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ ํ†ตํ•ฉ ์Šคํ‚ค๋งˆ ์‚ฌ์šฉ // ๋‚ด ๋ชจ์ž„๋ฐฉ ๊ธฐ๋ก/ํˆฌํ‘œ์— ๋Œ“๊ธ€์ด ๋‹ฌ๋ฆฐ ๊ฒฝ์šฐ @Builder - public record RoomRecordCommentedEvent(Long targetUserId, Long actorUserId, String actorUsername, - Long roomId, Integer page, Long postId, String postType) {} + public record RoomPostCommentedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long roomId, Integer page, Long postId, String postType) {} // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ์— ์ƒˆ๋กœ์šด ํˆฌํ‘œ๊ฐ€ ์‹œ์ž‘๋œ ๊ฒฝ์šฐ @Builder @@ -41,6 +41,11 @@ public record RoomCommentLikedEvent(Long targetUserId, Long actorUserId, String // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ์˜ ๋‚˜์˜ ๊ธฐ๋ก์ด ์ข‹์•„์š”๋ฅผ ๋ฐ›๋Š” ๊ฒฝ์šฐ @Builder - public record RoomRecordLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, + public record RoomPostLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long roomId, Integer page, Long postId, String postType) {} + + // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ์˜ ๋‚˜์˜ ๋Œ“๊ธ€์— ๋Œ€๋Œ“๊ธ€์ด ๋‹ฌ๋ฆฐ ๊ฒฝ์šฐ + @Builder + public record RoomPostCommentRepliedEvent(Long targetUserId, Long actorUserId, String actorUsername, Long roomId, Integer page, Long postId, String postType) {} } \ No newline at end of file diff --git a/src/main/java/konkuk/thip/message/application/port/in/RoomNotificationDispatchUseCase.java b/src/main/java/konkuk/thip/message/application/port/in/RoomNotificationDispatchUseCase.java index 124ab1344..2e3ac389d 100644 --- a/src/main/java/konkuk/thip/message/application/port/in/RoomNotificationDispatchUseCase.java +++ b/src/main/java/konkuk/thip/message/application/port/in/RoomNotificationDispatchUseCase.java @@ -3,7 +3,7 @@ import konkuk.thip.message.adapter.out.event.dto.RoomEvents; public interface RoomNotificationDispatchUseCase { - void handleRoomRecordCommented(RoomEvents.RoomRecordCommentedEvent e); + void handleRoomPostCommented(RoomEvents.RoomPostCommentedEvent e); void handleRoomVoteStarted(RoomEvents.RoomVoteStartedEvent e); @@ -17,5 +17,7 @@ public interface RoomNotificationDispatchUseCase { void handleRoomCommentLiked(RoomEvents.RoomCommentLikedEvent e); - void handleRoomRecordLiked(RoomEvents.RoomRecordLikedEvent e); + void handleRoomPostLiked(RoomEvents.RoomPostLikedEvent e); + + void handleRoomPostCommentReplied(RoomEvents.RoomPostCommentRepliedEvent e); } \ No newline at end of file diff --git a/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java b/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java index a7450abe5..987984220 100644 --- a/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java +++ b/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java @@ -3,8 +3,8 @@ public interface RoomEventCommandPort { // ๋‚ด ๋ชจ์ž„๋ฐฉ ๊ธฐ๋ก/ํˆฌํ‘œ์— ๋Œ“๊ธ€์ด ๋‹ฌ๋ฆฐ ๊ฒฝ์šฐ - void publishRoomRecordCommentedEvent(Long targetUserId, Long actorUserId, String actorUsername, - Long roomId, Integer page, Long postId, String postType); + void publishRoomPostCommentedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long roomId, Integer page, Long postId, String postType); // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ์— ์ƒˆ๋กœ์šด ํˆฌํ‘œ๊ฐ€ ์‹œ์ž‘๋œ ๊ฒฝ์šฐ void publishRoomVoteStartedEvent(Long targetUserId, Long roomId, String roomTitle, @@ -29,6 +29,9 @@ void publishRoomCommentLikedEvent(Long targetUserId, Long actorUserId, String ac Long roomId, Integer page, Long postId); // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ ์•ˆ์˜ ๋‚˜์˜ ๊ธฐ๋ก/ํˆฌํ‘œ๊ฐ€ ์ข‹์•„์š”๋ฅผ ๋ฐ›๋Š” ๊ฒฝ์šฐ - void publishRoomRecordLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, - Long roomId, Integer page, Long postId, String postType); + void publishRoomPostLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long roomId, Integer page, Long postId, String postType); + + void publicRoomPostCommentRepliedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long roomId, Integer page, Long postId, String postType); } \ No newline at end of file diff --git a/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java b/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java index 09e83770e..bb6c1b1ab 100644 --- a/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java +++ b/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java @@ -25,7 +25,7 @@ public class RoomNotificationDispatchService implements RoomNotificationDispatch private final FirebaseMessagingPort firebasePort; @Override - public void handleRoomRecordCommented(final RoomEvents.RoomRecordCommentedEvent event) { + public void handleRoomPostCommented(final RoomEvents.RoomPostCommentedEvent event) { Notification notification = buildNotification("์ƒˆ๋กœ์šด ๋Œ“๊ธ€์ด ๋‹ฌ๋ ธ์–ด์š”", "@" + event.actorUsername() + " ๋‹˜์ด ๋‚ด ๋…์„œ๊ธฐ๋ก์— ๋Œ“๊ธ€์„ ๋‹ฌ์•˜์–ด์š”!"); @@ -152,7 +152,7 @@ public void handleRoomCommentLiked(final RoomEvents.RoomCommentLikedEvent event) } @Override - public void handleRoomRecordLiked(final RoomEvents.RoomRecordLikedEvent event) { + public void handleRoomPostLiked(final RoomEvents.RoomPostLikedEvent event) { Notification notification = buildNotification("์ข‹์•„์š” ์•Œ๋ฆผ", "@" + event.actorUsername() + " ๋‹˜์ด ๋‚ด ๋…์„œ๊ธฐ๋ก์— ์ข‹์•„์š”๋ฅผ ๋ˆŒ๋ €์–ด์š”!"); @@ -176,6 +176,32 @@ public void handleRoomRecordLiked(final RoomEvents.RoomRecordLikedEvent event) { firebasePort.sendBatch(msgs, tk, dev); } + @Override + public void handleRoomPostCommentReplied(RoomEvents.RoomPostCommentRepliedEvent e) { + Notification notification = buildNotification("์ƒˆ๋กœ์šด ๋Œ“๊ธ€์ด ๋‹ฌ๋ ธ์–ด์š”", + "@" + e.actorUsername() + " ๋‹˜์ด ๋‚ด ๋Œ“๊ธ€์— ๋Œ€๋Œ“๊ธ€์„ ๋‹ฌ์•˜์–ด์š”!"); + + List tokens = fcmTokenQueryPort.findEnabledByUserId(e.targetUserId()); + if (tokens.isEmpty()) return; + + List msgs = new ArrayList<>(tokens.size()); + List tk = new ArrayList<>(tokens.size()); + List dev = new ArrayList<>(tokens.size()); + + for (FcmToken t : tokens) { + Message m = buildMessage(t.getFcmToken(), notification, + MessageRoute.ROOM_RECORD_DETAIL, + "roomId", String.valueOf(e.roomId()), + "page", String.valueOf(e.page()), + "type", "group", + "postId", String.valueOf(e.postId()), + "postType", e.postType()); + + msgs.add(m); tk.add(t.getFcmToken()); dev.add(t.getDeviceId()); + } + firebasePort.sendBatch(msgs, tk, dev); + } + // ===== helpers ===== private void pushRoomMain(Long targetUserId, Long roomId, Notification notification) { From 9ac24c1b6724b4a6c17f821e4153de5cc2190d29 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 01:28:00 +0900 Subject: [PATCH 35/93] =?UTF-8?q?[feat]=20=ED=8C=94=EB=A1=9C=EC=9A=B0=20?= =?UTF-8?q?=ED=91=B8=EC=89=AC=EC=95=8C=EB=A6=BC=20=EC=A0=84=EC=86=A1=20?= =?UTF-8?q?=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EB=B0=9C=ED=96=89=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/following/UserFollowService.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/konkuk/thip/user/application/service/following/UserFollowService.java b/src/main/java/konkuk/thip/user/application/service/following/UserFollowService.java index d47406f49..24e9eeb4c 100644 --- a/src/main/java/konkuk/thip/user/application/service/following/UserFollowService.java +++ b/src/main/java/konkuk/thip/user/application/service/following/UserFollowService.java @@ -1,6 +1,7 @@ package konkuk.thip.user.application.service.following; import konkuk.thip.common.exception.BusinessException; +import konkuk.thip.message.application.port.out.FeedEventCommandPort; import konkuk.thip.user.application.port.in.UserFollowUsecase; import konkuk.thip.user.application.port.in.dto.UserFollowCommand; import konkuk.thip.user.application.port.out.FollowingCommandPort; @@ -22,6 +23,8 @@ public class UserFollowService implements UserFollowUsecase { private final FollowingCommandPort followingCommandPort; private final UserCommandPort userCommandPort; + private final FeedEventCommandPort feedEventCommandPort; + @Override @Transactional public Boolean changeFollowingState(UserFollowCommand followCommand) { @@ -39,6 +42,9 @@ public Boolean changeFollowingState(UserFollowCommand followCommand) { if (isFollowRequest) { // ํŒ”๋กœ์šฐ ์š”์ฒญ์ธ ๊ฒฝ์šฐ targetUser.increaseFollowerCount(); followingCommandPort.save(Following.withoutId(userId, targetUserId), targetUser); + + // ํŒ”๋กœ์šฐ ํ‘ธ์‰ฌ์•Œ๋ฆผ ์ „์†ก + sendNotifications(userId, targetUserId); return true; } else { // ์–ธํŒ”๋กœ์šฐ ์š”์ฒญ์ธ ๊ฒฝ์šฐ targetUser.decreaseFollowerCount(); @@ -47,6 +53,11 @@ public Boolean changeFollowingState(UserFollowCommand followCommand) { } } + private void sendNotifications(Long userId, Long targetUserId) { + User actorUser = userCommandPort.findById(userId); + feedEventCommandPort.publishFollowEvent(targetUserId, actorUser.getId(), actorUser.getNickname()); + } + private void validateParams(Long userId, Long targetUserId) { if(userId.equals(targetUserId)) { throw new BusinessException(USER_CANNOT_FOLLOW_SELF); From 980706dd8427aef412a5d4c65f613af832739721 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 01:28:33 +0900 Subject: [PATCH 36/93] =?UTF-8?q?[feat]=20=EB=B0=A9=20=EC=A1=B0=EA=B8=B0?= =?UTF-8?q?=EB=A7=88=EA=B0=90=20=ED=91=B8=EC=89=AC=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=A0=84=EC=86=A1=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EB=B0=9C?= =?UTF-8?q?=ED=96=89=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/RoomRecruitCloseService.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/konkuk/thip/room/application/service/RoomRecruitCloseService.java b/src/main/java/konkuk/thip/room/application/service/RoomRecruitCloseService.java index e8c37d33b..0b8140a9a 100644 --- a/src/main/java/konkuk/thip/room/application/service/RoomRecruitCloseService.java +++ b/src/main/java/konkuk/thip/room/application/service/RoomRecruitCloseService.java @@ -2,6 +2,7 @@ import konkuk.thip.common.exception.BusinessException; import konkuk.thip.common.exception.code.ErrorCode; +import konkuk.thip.message.application.port.out.RoomEventCommandPort; import konkuk.thip.room.application.port.in.RoomRecruitCloseUseCase; import konkuk.thip.room.application.port.out.RoomCommandPort; import konkuk.thip.room.application.port.out.RoomParticipantCommandPort; @@ -11,6 +12,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; + @Service @RequiredArgsConstructor public class RoomRecruitCloseService implements RoomRecruitCloseUseCase { @@ -18,7 +21,8 @@ public class RoomRecruitCloseService implements RoomRecruitCloseUseCase { private final RoomParticipantCommandPort roomParticipantCommandPort; private final RoomCommandPort roomCommandPort; - //todo ๋ชจ์ง‘ ๋งˆ๊ฐ์‹œ ๋ฐฉ ์ฐธ์—ฌ์ž๋“ค์—๊ฒŒ ๋ชจ์ง‘ ๋งˆ๊ฐ ์•Œ๋ฆผ ์ „์†ก + private final RoomEventCommandPort roomEventCommandPort; + @Override @Transactional public Long closeRoomRecruit(Long userId, Long roomId) { @@ -37,9 +41,19 @@ public Long closeRoomRecruit(Long userId, Long roomId) { // 4. Room ํ…Œ์ด๋ธ” ์—…๋ฐ์ดํŠธ roomCommandPort.update(room); + // 5. ๋ฐฉ ์ฐธ์—ฌ์ž๋“ค์—๊ฒŒ ๋ชจ์ง‘ ๋งˆ๊ฐ ์•Œ๋ฆผ ์ „์†ก (ํ˜ธ์ŠคํŠธ ์ œ์™ธ) + sendNotifications(roomId, room); + return room.getId(); } + private void sendNotifications(Long roomId, Room room) { + List actorUsers = roomParticipantCommandPort.findAllByRoomId(roomId); + for (RoomParticipant participant : actorUsers) { + if(participant.isHost()) continue; // ํ˜ธ์ŠคํŠธ๋Š” ์ œ์™ธ + roomEventCommandPort.publishRoomRecruitClosedEarlyEvent(participant.getUserId(), roomId, room.getTitle()); + } + } private void validateCloseable(RoomParticipant roomParticipant) { if (roomParticipant.isMember()) { From 37866a4055c44aa95442513a156f1aed06a2478a Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 01:29:26 +0900 Subject: [PATCH 37/93] =?UTF-8?q?[feat]=20=EB=8C=93=EA=B8=80=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EB=B0=9C=ED=96=89?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=9C=20PostQueryDto=20=EB=B0=8F=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=BF=BC=EB=A6=AC=20=EC=A0=95=EC=9D=98=20?= =?UTF-8?q?(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FeedCommandPersistenceAdapter.java | 6 ++++ .../repository/FeedQueryRepository.java | 4 ++- .../repository/FeedQueryRepositoryImpl.java | 17 +++++++++ .../application/port/out/FeedCommandPort.java | 3 ++ .../port/out/dto/PostQueryDto.java | 29 +++++++++++++++ .../service/handler/PostHandler.java | 8 +++++ .../RecordCommandPersistenceAdapter.java | 6 ++++ .../record/RecordQueryRepository.java | 3 ++ .../record/RecordQueryRepositoryImpl.java | 35 +++++++++++++++++++ .../port/out/RecordCommandPort.java | 3 ++ 10 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 src/main/java/konkuk/thip/post/application/port/out/dto/PostQueryDto.java diff --git a/src/main/java/konkuk/thip/feed/adapter/out/persistence/FeedCommandPersistenceAdapter.java b/src/main/java/konkuk/thip/feed/adapter/out/persistence/FeedCommandPersistenceAdapter.java index 792b63b55..3295eafe7 100644 --- a/src/main/java/konkuk/thip/feed/adapter/out/persistence/FeedCommandPersistenceAdapter.java +++ b/src/main/java/konkuk/thip/feed/adapter/out/persistence/FeedCommandPersistenceAdapter.java @@ -9,6 +9,7 @@ import konkuk.thip.feed.adapter.out.persistence.repository.SavedFeedJpaRepository; import konkuk.thip.feed.application.port.out.FeedCommandPort; import konkuk.thip.feed.domain.Feed; +import konkuk.thip.post.application.port.out.dto.PostQueryDto; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import lombok.RequiredArgsConstructor; @@ -80,6 +81,11 @@ public void deleteSavedFeed(Long userId, Long feedId) { savedFeedJpaRepository.deleteByUserIdAndFeedId(userId, feedId); } + @Override + public PostQueryDto getPostQueryDtoById(Long postId) { + return feedJpaRepository.getPostQueryDtoByPostId(postId); + } + @Override public void delete(Feed feed) { FeedJpaEntity feedJpaEntity = feedJpaRepository.findByPostId(feed.getId()) diff --git a/src/main/java/konkuk/thip/feed/adapter/out/persistence/repository/FeedQueryRepository.java b/src/main/java/konkuk/thip/feed/adapter/out/persistence/repository/FeedQueryRepository.java index e6321fb01..9f7db6baf 100644 --- a/src/main/java/konkuk/thip/feed/adapter/out/persistence/repository/FeedQueryRepository.java +++ b/src/main/java/konkuk/thip/feed/adapter/out/persistence/repository/FeedQueryRepository.java @@ -1,7 +1,7 @@ package konkuk.thip.feed.adapter.out.persistence.repository; -import konkuk.thip.feed.application.port.out.dto.TagCategoryQueryDto; import konkuk.thip.feed.application.port.out.dto.FeedQueryDto; +import konkuk.thip.post.application.port.out.dto.PostQueryDto; import java.time.LocalDateTime; import java.util.List; @@ -25,4 +25,6 @@ public interface FeedQueryRepository { List findLatestPublicFeedCreatorsIn(Set userIds, int size); List findSavedFeedsByCreatedAt(Long userId, LocalDateTime lastCreatedAt, int size); + + PostQueryDto getPostQueryDtoByPostId(Long postId); } diff --git a/src/main/java/konkuk/thip/feed/adapter/out/persistence/repository/FeedQueryRepositoryImpl.java b/src/main/java/konkuk/thip/feed/adapter/out/persistence/repository/FeedQueryRepositoryImpl.java index 4951ecb2e..9ca87dc50 100644 --- a/src/main/java/konkuk/thip/feed/adapter/out/persistence/repository/FeedQueryRepositoryImpl.java +++ b/src/main/java/konkuk/thip/feed/adapter/out/persistence/repository/FeedQueryRepositoryImpl.java @@ -13,6 +13,8 @@ import konkuk.thip.feed.adapter.out.jpa.QSavedFeedJpaEntity; import konkuk.thip.feed.application.port.out.dto.FeedQueryDto; import konkuk.thip.feed.application.port.out.dto.QFeedQueryDto; +import konkuk.thip.post.application.port.out.dto.PostQueryDto; +import konkuk.thip.post.application.port.out.dto.QPostQueryDto; import konkuk.thip.user.adapter.out.jpa.QFollowingJpaEntity; import konkuk.thip.user.adapter.out.jpa.QUserJpaEntity; import lombok.RequiredArgsConstructor; @@ -388,6 +390,21 @@ public List findSavedFeedsByCreatedAt(Long userId, LocalDateTime l .fetch(); } + @Override + public PostQueryDto getPostQueryDtoByPostId(Long postId) { + return jpaQueryFactory + .select(new QPostQueryDto( + feed.postId, + feed.userJpaEntity.userId, + feed.dtype, + Expressions.nullExpression(), + Expressions.nullExpression() + )) + .from(feed) + .where(feed.postId.eq(postId)) + .fetchOne(); + } + /** * SavedFeed ์ „์šฉ DTO ๋งคํ•‘ */ diff --git a/src/main/java/konkuk/thip/feed/application/port/out/FeedCommandPort.java b/src/main/java/konkuk/thip/feed/application/port/out/FeedCommandPort.java index 40dea9122..d24b332b9 100644 --- a/src/main/java/konkuk/thip/feed/application/port/out/FeedCommandPort.java +++ b/src/main/java/konkuk/thip/feed/application/port/out/FeedCommandPort.java @@ -3,6 +3,7 @@ import konkuk.thip.common.exception.EntityNotFoundException; import konkuk.thip.feed.domain.Feed; +import konkuk.thip.post.application.port.out.dto.PostQueryDto; import java.util.Optional; @@ -19,4 +20,6 @@ default Feed getByIdOrThrow(Long id) { void delete(Feed feed); void saveSavedFeed(Long userId, Long feedId); void deleteSavedFeed(Long userId, Long feedId); + + PostQueryDto getPostQueryDtoById(Long postId); } diff --git a/src/main/java/konkuk/thip/post/application/port/out/dto/PostQueryDto.java b/src/main/java/konkuk/thip/post/application/port/out/dto/PostQueryDto.java new file mode 100644 index 000000000..760a9679e --- /dev/null +++ b/src/main/java/konkuk/thip/post/application/port/out/dto/PostQueryDto.java @@ -0,0 +1,29 @@ +package konkuk.thip.post.application.port.out.dto; + +import com.querydsl.core.annotations.QueryProjection; +import jakarta.annotation.Nullable; + +public record PostQueryDto( + Long postId, + Long creatorId, + String postType, + @Nullable Integer page, + @Nullable Long roomId +) { + @QueryProjection + public PostQueryDto( + Long postId, + Long creatorId, + String postType, + @Nullable Integer page, + @Nullable Long roomId + ) { + this.postId = postId; + this.creatorId = creatorId; + this.postType = postType; + this.page = page; + this.roomId = roomId; + } + + +} diff --git a/src/main/java/konkuk/thip/post/application/service/handler/PostHandler.java b/src/main/java/konkuk/thip/post/application/service/handler/PostHandler.java index a2bfaa4a8..978361b0d 100644 --- a/src/main/java/konkuk/thip/post/application/service/handler/PostHandler.java +++ b/src/main/java/konkuk/thip/post/application/service/handler/PostHandler.java @@ -1,6 +1,7 @@ package konkuk.thip.post.application.service.handler; import konkuk.thip.common.annotation.application.HelperService; +import konkuk.thip.post.application.port.out.dto.PostQueryDto; import konkuk.thip.post.domain.CountUpdatable; import konkuk.thip.post.domain.PostType; import konkuk.thip.feed.application.port.out.FeedCommandPort; @@ -34,4 +35,11 @@ public void updatePost(PostType type, CountUpdatable post) { case VOTE -> voteCommandPort.updateVote((Vote) post); } } + + public PostQueryDto getPostQueryDto(PostType type, Long postId) { + return switch (type) { + case FEED -> feedCommandPort.getPostQueryDtoById(postId); + default -> recordCommandPort.getPostQueryDtoById(postId); + }; + } } diff --git a/src/main/java/konkuk/thip/roompost/adapter/out/persistence/RecordCommandPersistenceAdapter.java b/src/main/java/konkuk/thip/roompost/adapter/out/persistence/RecordCommandPersistenceAdapter.java index b327f9c1a..ae26a63c5 100644 --- a/src/main/java/konkuk/thip/roompost/adapter/out/persistence/RecordCommandPersistenceAdapter.java +++ b/src/main/java/konkuk/thip/roompost/adapter/out/persistence/RecordCommandPersistenceAdapter.java @@ -1,6 +1,7 @@ package konkuk.thip.roompost.adapter.out.persistence; import konkuk.thip.common.exception.EntityNotFoundException; +import konkuk.thip.post.application.port.out.dto.PostQueryDto; import konkuk.thip.roompost.adapter.out.jpa.RecordJpaEntity; import konkuk.thip.roompost.adapter.out.mapper.RecordMapper; import konkuk.thip.roompost.adapter.out.persistence.repository.record.RecordJpaRepository; @@ -57,6 +58,11 @@ public void delete(Record record) { recordJpaRepository.save(recordJpaEntity); } + @Override + public PostQueryDto getPostQueryDtoById(Long postId) { + return recordJpaRepository.getPostQueryDtoByPostId(postId); + } + @Override public void update(Record record) { RecordJpaEntity recordJpaEntity = recordJpaRepository.findByPostId(record.getId()).orElseThrow( diff --git a/src/main/java/konkuk/thip/roompost/adapter/out/persistence/repository/record/RecordQueryRepository.java b/src/main/java/konkuk/thip/roompost/adapter/out/persistence/repository/record/RecordQueryRepository.java index 936f14737..e1632d06c 100644 --- a/src/main/java/konkuk/thip/roompost/adapter/out/persistence/repository/record/RecordQueryRepository.java +++ b/src/main/java/konkuk/thip/roompost/adapter/out/persistence/repository/record/RecordQueryRepository.java @@ -1,6 +1,7 @@ package konkuk.thip.roompost.adapter.out.persistence.repository.record; import konkuk.thip.common.util.Cursor; +import konkuk.thip.post.application.port.out.dto.PostQueryDto; import konkuk.thip.roompost.adapter.out.persistence.RoomPostSortType; import konkuk.thip.roompost.application.port.out.dto.RoomPostQueryDto; @@ -11,4 +12,6 @@ public interface RecordQueryRepository { List findMyRecords(Long roomId, Long userId, Cursor cursor); List findGroupRecordsOrderBySortType(Long roomId, Long userId, Cursor cursor, Integer pageStart, Integer pageEnd, Boolean isOverview, RoomPostSortType roomPostSortType); + + PostQueryDto getPostQueryDtoByPostId(Long postId); } diff --git a/src/main/java/konkuk/thip/roompost/adapter/out/persistence/repository/record/RecordQueryRepositoryImpl.java b/src/main/java/konkuk/thip/roompost/adapter/out/persistence/repository/record/RecordQueryRepositoryImpl.java index 2376fc136..fbe50c2b8 100644 --- a/src/main/java/konkuk/thip/roompost/adapter/out/persistence/repository/record/RecordQueryRepositoryImpl.java +++ b/src/main/java/konkuk/thip/roompost/adapter/out/persistence/repository/record/RecordQueryRepositoryImpl.java @@ -7,6 +7,8 @@ import com.querydsl.jpa.impl.JPAQueryFactory; import konkuk.thip.common.util.Cursor; import konkuk.thip.post.adapter.out.jpa.QPostJpaEntity; +import konkuk.thip.post.application.port.out.dto.PostQueryDto; +import konkuk.thip.post.application.port.out.dto.QPostQueryDto; import konkuk.thip.roompost.adapter.out.jpa.QRecordJpaEntity; import konkuk.thip.roompost.adapter.out.jpa.QVoteJpaEntity; import konkuk.thip.roompost.adapter.out.persistence.RoomPostSortType; @@ -199,4 +201,37 @@ private QRoomPostQueryDto selectPostQueryDto() { isOverviewExpr().eq(1) ); } + + @Override + public PostQueryDto getPostQueryDtoByPostId(Long postId) { + return queryFactory + .select(new QPostQueryDto( + post.postId, + post.userJpaEntity.userId, + post.dtype, + pageExprForDto(), // dtype์— ๋”ฐ๋ผ Record/Vote์˜ page + roomIdExprForDto() // dtype์— ๋”ฐ๋ผ Record/Vote์˜ roomId + )) + .from(post) + .where(post.postId.eq(postId)) + .fetchOne(); + } + + private NumberExpression pageExprForDto() { + return new CaseBuilder() + .when(post.dtype.eq(RECORD.getType())) + .then(treat(post, QRecordJpaEntity.class).page) + .when(post.dtype.eq(VOTE.getType())) + .then(treat(post, QVoteJpaEntity.class).page) + .otherwise((Integer) null); + } + + private NumberExpression roomIdExprForDto() { + return new CaseBuilder() + .when(post.dtype.eq(RECORD.getType())) + .then(treat(post, QRecordJpaEntity.class).roomJpaEntity.roomId) + .when(post.dtype.eq(VOTE.getType())) + .then(treat(post, QVoteJpaEntity.class).roomJpaEntity.roomId) + .otherwise((Long) null); + } } diff --git a/src/main/java/konkuk/thip/roompost/application/port/out/RecordCommandPort.java b/src/main/java/konkuk/thip/roompost/application/port/out/RecordCommandPort.java index 16b5ceb9a..ed3aacb71 100644 --- a/src/main/java/konkuk/thip/roompost/application/port/out/RecordCommandPort.java +++ b/src/main/java/konkuk/thip/roompost/application/port/out/RecordCommandPort.java @@ -2,6 +2,7 @@ import konkuk.thip.common.exception.EntityNotFoundException; +import konkuk.thip.post.application.port.out.dto.PostQueryDto; import konkuk.thip.roompost.domain.Record; import java.util.Optional; @@ -22,4 +23,6 @@ default Record getByIdOrThrow(Long id) { } void delete(Record record); + + PostQueryDto getPostQueryDtoById(Long postId); } From 69e3120630f0769587607a60ce3aeecf68b636c4 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 01:29:45 +0900 Subject: [PATCH 38/93] =?UTF-8?q?[feat]=20=ED=8C=94=EB=A1=9C=EC=9B=8C?= =?UTF-8?q?=EC=97=90=EA=B2=8C=20=EC=83=88=EB=A1=9C=EC=9A=B4=20=ED=94=BC?= =?UTF-8?q?=EB=93=9C=20=EB=93=B1=EB=A1=9D=20=ED=91=B8=EC=89=AC=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EC=A0=84=EC=86=A1=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EB=B0=9C=ED=96=89=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/FeedCreateService.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/main/java/konkuk/thip/feed/application/service/FeedCreateService.java b/src/main/java/konkuk/thip/feed/application/service/FeedCreateService.java index 355e1ba66..bc6e2f1d0 100644 --- a/src/main/java/konkuk/thip/feed/application/service/FeedCreateService.java +++ b/src/main/java/konkuk/thip/feed/application/service/FeedCreateService.java @@ -9,13 +9,19 @@ import konkuk.thip.feed.application.port.in.dto.FeedCreateCommand; import konkuk.thip.feed.application.port.out.FeedCommandPort; import konkuk.thip.feed.domain.Feed; +import konkuk.thip.feed.domain.value.ContentList; import konkuk.thip.feed.domain.value.Tag; import konkuk.thip.feed.domain.value.TagList; -import konkuk.thip.feed.domain.value.ContentList; +import konkuk.thip.message.application.port.out.FeedEventCommandPort; +import konkuk.thip.user.application.port.out.FollowingQueryPort; +import konkuk.thip.user.application.port.out.UserCommandPort; +import konkuk.thip.user.domain.User; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; + @Service @RequiredArgsConstructor public class FeedCreateService implements FeedCreateUseCase { @@ -23,8 +29,11 @@ public class FeedCreateService implements FeedCreateUseCase { private final BookCommandPort bookCommandPort; private final FeedCommandPort feedCommandPort; private final BookApiQueryPort bookApiQueryPort; + private final FollowingQueryPort followingQueryPort; + private final UserCommandPort userCommandPort; private final ImageUrlValidationService imageUrlValidationService; + private final FeedEventCommandPort feedEventCommandPort; @Override @Transactional @@ -48,9 +57,21 @@ public Long createFeed(FeedCreateCommand command) { command.tagList(), command.imageUrls() ); + + // 4. ํ”ผ๋“œ ์ž‘์„ฑ ํ‘ธ์‰ฌ ์•Œ๋ฆผ ์ „์†ก + sendNotifications(command, feed); + return feedCommandPort.save(feed); } + private void sendNotifications(FeedCreateCommand command, Feed feed) { + List targetUsers = followingQueryPort.getAllFollowersByUserId(command.userId()); + User actorUser = userCommandPort.findById(command.userId()); + for (User targetUser : targetUsers) { + feedEventCommandPort.publishFolloweeNewPostEvent(targetUser.getId(), actorUser.getId(), actorUser.getNickname(), feed.getId()); + } + } + /** * ISBN์œผ๋กœ ์ฑ…์„ ์กฐํšŒํ•˜๊ณ , ์—†์œผ๋ฉด ์™ธ๋ถ€ API(Naver)์—์„œ ์ƒ์„ธ ์ •๋ณด๋ฅผ ์กฐํšŒํ•ด ์ƒˆ๋กœ ์ €์žฅ ํ›„ ID ๋ฐ˜ํ™˜ */ From ba59113602a5d65a858a10c9c1f1fb6bd231aea5 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 01:29:50 +0900 Subject: [PATCH 39/93] =?UTF-8?q?[feat]=20=EB=8C=93=EA=B8=80=20=EC=A2=8B?= =?UTF-8?q?=EC=95=84=EC=9A=94=20=ED=91=B8=EC=89=AC=EC=95=8C=EB=A6=BC=20?= =?UTF-8?q?=EC=A0=84=EC=86=A1=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EB=B0=9C?= =?UTF-8?q?=ED=96=89=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/CommentLikeService.java | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/main/java/konkuk/thip/comment/application/service/CommentLikeService.java b/src/main/java/konkuk/thip/comment/application/service/CommentLikeService.java index fa4aa06c9..9cf48a718 100644 --- a/src/main/java/konkuk/thip/comment/application/service/CommentLikeService.java +++ b/src/main/java/konkuk/thip/comment/application/service/CommentLikeService.java @@ -8,8 +8,14 @@ import konkuk.thip.comment.application.port.out.CommentLikeQueryPort; import konkuk.thip.comment.application.service.validator.CommentAuthorizationValidator; import konkuk.thip.comment.domain.Comment; -import konkuk.thip.post.domain.CountUpdatable; +import konkuk.thip.message.application.port.out.FeedEventCommandPort; +import konkuk.thip.message.application.port.out.RoomEventCommandPort; +import konkuk.thip.post.application.port.out.dto.PostQueryDto; import konkuk.thip.post.application.service.handler.PostHandler; +import konkuk.thip.post.domain.CountUpdatable; +import konkuk.thip.post.domain.PostType; +import konkuk.thip.user.application.port.out.UserCommandPort; +import konkuk.thip.user.domain.User; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -21,10 +27,14 @@ public class CommentLikeService implements CommentLikeUseCase { private final CommentCommandPort commentCommandPort; private final CommentLikeQueryPort commentLikeQueryPort; private final CommentLikeCommandPort commentLikeCommandPort; + private final UserCommandPort userCommandPort; private final PostHandler postHandler; private final CommentAuthorizationValidator commentAuthorizationValidator; + private final FeedEventCommandPort feedEventCommandPort; + private final RoomEventCommandPort roomEventCommandPort; + @Override @Transactional public CommentIsLikeResult changeLikeStatusComment(CommentIsLikeCommand command) { @@ -42,6 +52,9 @@ public CommentIsLikeResult changeLikeStatusComment(CommentIsLikeCommand command) if (command.isLike()) { comment.validateCanLike(alreadyLiked); // ์ข‹์•„์š” ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ๊ฒ€์ฆ commentLikeCommandPort.save(command.userId(), command.commentId()); + + // ๋Œ“๊ธ€ ์ข‹์•„์š” ํ‘ธ์‰ฌ์•Œ๋ฆผ ์ „์†ก + sendNotifcations(command, comment); } else { comment.validateCanUnlike(alreadyLiked); // ์ข‹์•„์š” ์ทจ์†Œ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ๊ฒ€์ฆ commentLikeCommandPort.delete(command.userId(), command.commentId()); @@ -53,4 +66,16 @@ public CommentIsLikeResult changeLikeStatusComment(CommentIsLikeCommand command) return CommentIsLikeResult.of(comment.getId(), command.isLike()); } + + private void sendNotifcations(CommentIsLikeCommand command, Comment comment) { + User actorUser = userCommandPort.findById(command.userId()); + // ์ข‹์•„์š” ํ‘ธ์‰ฌ์•Œ๋ฆผ ์ „์†ก + if (comment.getPostType() == PostType.FEED) { + feedEventCommandPort.publishFeedCommentLikedEvent(comment.getCreatorId(), actorUser.getId(), actorUser.getNickname(), comment.getId()); + } + if (comment.getPostType() == PostType.RECORD || comment.getPostType() == PostType.VOTE) { + PostQueryDto postQueryDto = postHandler.getPostQueryDto(comment.getPostType(), comment.getTargetPostId()); + roomEventCommandPort.publishRoomCommentLikedEvent(comment.getCreatorId(), actorUser.getId(), actorUser.getNickname(), postQueryDto.roomId(), postQueryDto.page(), postQueryDto.postId()); + } + } } From b8c9e21a5347ef5316a58831653ab428f27c416b Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 01:30:00 +0900 Subject: [PATCH 40/93] =?UTF-8?q?[feat]=20=EB=8C=93=EA=B8=80=20=EB=B0=8F?= =?UTF-8?q?=20=EB=8B=B5=EA=B8=80=20=EB=93=B1=EB=A1=9D=20=ED=91=B8=EC=89=AC?= =?UTF-8?q?=EC=95=8C=EB=A6=BC=20=EC=A0=84=EC=86=A1=20=EC=9D=B4=EB=B2=A4?= =?UTF-8?q?=ED=8A=B8=20=EB=B0=9C=ED=96=89=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/CommentCreateService.java | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/src/main/java/konkuk/thip/comment/application/service/CommentCreateService.java b/src/main/java/konkuk/thip/comment/application/service/CommentCreateService.java index 0a61b2700..a905c2758 100644 --- a/src/main/java/konkuk/thip/comment/application/service/CommentCreateService.java +++ b/src/main/java/konkuk/thip/comment/application/service/CommentCreateService.java @@ -11,9 +11,14 @@ import konkuk.thip.comment.application.service.validator.CommentAuthorizationValidator; import konkuk.thip.comment.domain.Comment; import konkuk.thip.common.exception.InvalidStateException; +import konkuk.thip.message.application.port.out.FeedEventCommandPort; +import konkuk.thip.message.application.port.out.RoomEventCommandPort; +import konkuk.thip.post.application.port.out.dto.PostQueryDto; import konkuk.thip.post.domain.CountUpdatable; import konkuk.thip.post.application.service.handler.PostHandler; import konkuk.thip.post.domain.PostType; +import konkuk.thip.user.application.port.out.UserCommandPort; +import konkuk.thip.user.domain.User; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -29,11 +34,14 @@ public class CommentCreateService implements CommentCreateUseCase { private final CommentQueryPort commentQueryPort; private final CommentLikeQueryPort commentLikeQueryPort; private final CommentQueryMapper commentQueryMapper; - + private final UserCommandPort userCommandPort; private final PostHandler postHandler; private final CommentAuthorizationValidator commentAuthorizationValidator; + private final FeedEventCommandPort feedEventCommandPort; + private final RoomEventCommandPort roomEventCommandPort; + @Override @Transactional public CommentCreateResponse createComment(CommentCreateCommand command) { @@ -47,8 +55,8 @@ public CommentCreateResponse createComment(CommentCreateCommand command) { // 2-1. ๊ฒŒ์‹œ๊ธ€ ํƒ€์ž…์— ๋”ฐ๋ฅธ ๋Œ“๊ธ€ ์ƒ์„ฑ ๊ถŒํ•œ ๊ฒ€์ฆ commentAuthorizationValidator.validateUserCanAccessPostForComment(type, post, command.userId()); - // TODO ํ”ผ๋“œ: ๋‚ด ๊ฒŒ์‹œ๊ธ€์˜ ๋Œ“๊ธ€, ๋‚ด ๋Œ“๊ธ€์— ๋Œ€ํ•œ ๋‹ต๊ธ€ ์•Œ๋ฆผ ์ „์†ก - // TODO ๊ธฐ๋ก ๋ฐ ํˆฌํ‘œ: ๋ชจ์ž„๋ฐฉ์˜ ๋‚ด ๊ฒŒ์‹œ๊ธ€์— ๋Œ€ํ•œ ๋Œ“๊ธ€, ๋‚ด ๋Œ“๊ธ€์— ๋Œ€ํ•œ ๋‹ต๊ธ€ ์•Œ๋ฆผ ์ „์†ก + // 2-2. ํ‘ธ์‰ฌ ์•Œ๋ฆผ ์ „์†ก + sendNotifications(command, type, post); // 3. ๋Œ“๊ธ€ ์ƒ์„ฑ Long savedCommentId = createCommentDomain(command); @@ -74,7 +82,26 @@ public CommentCreateResponse createComment(CommentCreateCommand command) { CommentQueryDto savedCommentDto = commentQueryPort.findRootCommentById(savedCommentId); return commentQueryMapper.toRoot(savedCommentDto, false, command.userId()); } + } + private void sendNotifications(CommentCreateCommand command, PostType type, CountUpdatable post) { + PostQueryDto postQueryDto = postHandler.getPostQueryDto(type, post.getId()); + User actorUser = userCommandPort.findById(command.userId()); + if (type == PostType.FEED) { + // ํ”ผ๋“œ ๋Œ“๊ธ€ ์•Œ๋ฆผ ์ด๋ฒคํŠธ ๋ฐœํ–‰ + feedEventCommandPort.publishFeedCommentedEvent(postQueryDto.creatorId(), actorUser.getId(), actorUser.getNickname(), postQueryDto.postId()); + if (command.isReplyRequest()){ + // ํ”ผ๋“œ ๋‹ต๊ธ€ ์•Œ๋ฆผ ์ด๋ฒคํŠธ ๋ฐœํ–‰ + feedEventCommandPort.publishFeedRepliedEvent(postQueryDto.creatorId(), actorUser.getId(), actorUser.getNickname(), postQueryDto.postId()); + } + } else if (type == PostType.RECORD || type == PostType.VOTE) { + // ๋ชจ์ž„๋ฐฉ ๊ฒŒ์‹œ๊ธ€ ๋Œ“๊ธ€ ์•Œ๋ฆผ ์ด๋ฒคํŠธ ๋ฐœํ–‰ + roomEventCommandPort.publishRoomPostCommentedEvent(postQueryDto.creatorId(), actorUser.getId(), actorUser.getNickname(), postQueryDto.roomId(), postQueryDto.page(), postQueryDto.postId(), postQueryDto.postType()); + if (command.isReplyRequest()){ + // ๋ชจ์ž„๋ฐฉ ๊ฒŒ์‹œ๊ธ€ ๋‹ต๊ธ€ ์•Œ๋ฆผ ์ด๋ฒคํŠธ ๋ฐœํ–‰ + roomEventCommandPort.publicRoomPostCommentRepliedEvent(postQueryDto.creatorId(), actorUser.getId(), actorUser.getNickname(), postQueryDto.roomId(), postQueryDto.page(), postQueryDto.postId(), postQueryDto.postType()); + } + } } private Long createCommentDomain(CommentCreateCommand command) { From 22499633ff26e1d08145df711e0d210cde98ed74 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 01:30:22 +0900 Subject: [PATCH 41/93] =?UTF-8?q?[feat]=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=A2=8B=EC=95=84=EC=9A=94=20=ED=91=B8=EC=89=AC=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EC=A0=84=EC=86=A1=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EB=B0=9C=ED=96=89=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../out/persistence/FollowingQueryPersistenceAdapter.java | 6 ++++++ .../repository/following/FollowingJpaRepository.java | 6 ++++++ .../thip/user/application/port/out/FollowingQueryPort.java | 3 +++ 3 files changed, 15 insertions(+) diff --git a/src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingQueryPersistenceAdapter.java b/src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingQueryPersistenceAdapter.java index b8d9a774e..06182fd8a 100644 --- a/src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingQueryPersistenceAdapter.java +++ b/src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingQueryPersistenceAdapter.java @@ -7,6 +7,7 @@ import konkuk.thip.user.application.port.out.dto.UserQueryDto; import konkuk.thip.user.adapter.out.persistence.repository.following.FollowingJpaRepository; import konkuk.thip.user.application.port.out.FollowingQueryPort; +import konkuk.thip.user.domain.User; import konkuk.thip.user.domain.value.Alias; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; @@ -66,4 +67,9 @@ public int getFollowingCountByUser(Long userId) { public List findAllFollowingUsersOrderByFollowedAtDesc(Long userId) { return followingJpaRepository.findAllFollowingUsersOrderByFollowedAtDesc(userId); } + + @Override + public List getAllFollowersByUserId(Long userId) { + return followingJpaRepository.findAllFollowersByUserId(userId); + } } diff --git a/src/main/java/konkuk/thip/user/adapter/out/persistence/repository/following/FollowingJpaRepository.java b/src/main/java/konkuk/thip/user/adapter/out/persistence/repository/following/FollowingJpaRepository.java index 0ceae15ab..584e4d420 100644 --- a/src/main/java/konkuk/thip/user/adapter/out/persistence/repository/following/FollowingJpaRepository.java +++ b/src/main/java/konkuk/thip/user/adapter/out/persistence/repository/following/FollowingJpaRepository.java @@ -1,10 +1,13 @@ package konkuk.thip.user.adapter.out.persistence.repository.following; import konkuk.thip.user.adapter.out.jpa.FollowingJpaEntity; +import konkuk.thip.user.domain.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface FollowingJpaRepository extends JpaRepository, FollowingQueryRepository { @@ -13,4 +16,7 @@ public interface FollowingJpaRepository extends JpaRepository findAllFollowersByUserId(Long userId); } diff --git a/src/main/java/konkuk/thip/user/application/port/out/FollowingQueryPort.java b/src/main/java/konkuk/thip/user/application/port/out/FollowingQueryPort.java index 3597d83c0..8b540d09f 100644 --- a/src/main/java/konkuk/thip/user/application/port/out/FollowingQueryPort.java +++ b/src/main/java/konkuk/thip/user/application/port/out/FollowingQueryPort.java @@ -3,6 +3,7 @@ import konkuk.thip.common.util.CursorBasedList; import konkuk.thip.user.application.port.out.dto.FollowingQueryDto; import konkuk.thip.user.application.port.out.dto.UserQueryDto; +import konkuk.thip.user.domain.User; import java.util.List; @@ -20,5 +21,7 @@ public interface FollowingQueryPort { * user๊ฐ€ ํŒ”๋กœ์ž‰ํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์„ ์กฐํšŒ */ List findAllFollowingUsersOrderByFollowedAtDesc(Long userId); + + List getAllFollowersByUserId(Long userId); } From c56509482ea5e3f2c5029ea7264de0ba4a63e169 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 01:30:25 +0900 Subject: [PATCH 42/93] =?UTF-8?q?[feat]=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20?= =?UTF-8?q?=EC=A2=8B=EC=95=84=EC=9A=94=20=ED=91=B8=EC=89=AC=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EC=A0=84=EC=86=A1=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EB=B0=9C=ED=96=89=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/service/PostLikeService.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/main/java/konkuk/thip/post/application/service/PostLikeService.java b/src/main/java/konkuk/thip/post/application/service/PostLikeService.java index 21c0effcb..09a179bf6 100644 --- a/src/main/java/konkuk/thip/post/application/service/PostLikeService.java +++ b/src/main/java/konkuk/thip/post/application/service/PostLikeService.java @@ -1,5 +1,8 @@ package konkuk.thip.post.application.service; +import konkuk.thip.message.application.port.out.FeedEventCommandPort; +import konkuk.thip.message.application.port.out.RoomEventCommandPort; +import konkuk.thip.post.application.port.out.dto.PostQueryDto; import konkuk.thip.post.application.service.handler.PostHandler; import konkuk.thip.post.domain.CountUpdatable; import konkuk.thip.post.application.port.in.dto.PostIsLikeCommand; @@ -8,7 +11,10 @@ import konkuk.thip.post.application.port.out.PostLikeCommandPort; import konkuk.thip.post.application.port.out.PostLikeQueryPort; import konkuk.thip.post.application.service.validator.PostLikeAuthorizationValidator; +import konkuk.thip.post.domain.PostType; import konkuk.thip.post.domain.service.PostCountService; +import konkuk.thip.user.application.port.out.UserCommandPort; +import konkuk.thip.user.domain.User; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -19,11 +25,15 @@ public class PostLikeService implements PostLikeUseCase { private final PostLikeQueryPort postLikeQueryPort; private final PostLikeCommandPort postLikeCommandPort; + private final UserCommandPort userCommandPort; private final PostHandler postHandler; private final PostCountService postCountService; private final PostLikeAuthorizationValidator postLikeAuthorizationValidator; + private final FeedEventCommandPort feedEventCommandPort; + private final RoomEventCommandPort roomEventCommandPort; + @Override @Transactional public PostIsLikeResult changeLikeStatusPost(PostIsLikeCommand command) { @@ -41,6 +51,9 @@ public PostIsLikeResult changeLikeStatusPost(PostIsLikeCommand command) { if (command.isLike()) { postLikeAuthorizationValidator.validateUserCanLike(alreadyLiked); // ์ข‹์•„์š” ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ๊ฒ€์ฆ postLikeCommandPort.save(command.userId(), command.postId(),command.postType()); + + // ์ข‹์•„์š” ํ‘ธ์‰ฌ์•Œ๋ฆผ ์ „์†ก + sendNotifications(command); } else { postLikeAuthorizationValidator.validateUserCanUnLike(alreadyLiked); // ์ข‹์•„์š” ์ทจ์†Œ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ๊ฒ€์ฆ postLikeCommandPort.delete(command.userId(), command.postId()); @@ -52,4 +65,16 @@ public PostIsLikeResult changeLikeStatusPost(PostIsLikeCommand command) { return PostIsLikeResult.of(post.getId(), command.isLike()); } + + private void sendNotifications(PostIsLikeCommand command) { + PostQueryDto postQueryDto = postHandler.getPostQueryDto(command.postType(), command.postId()); + User actorUser = userCommandPort.findById(command.userId()); + // ์ข‹์•„์š” ํ‘ธ์‰ฌ์•Œ๋ฆผ ์ „์†ก + if (command.postType() == PostType.FEED) { + feedEventCommandPort.publishFeedLikedEvent(postQueryDto.creatorId(), actorUser.getId(), actorUser.getNickname(), postQueryDto.postId()); + } + if (command.postType() == PostType.RECORD || command.postType() == PostType.VOTE) { + roomEventCommandPort.publishRoomPostLikedEvent(postQueryDto.creatorId(), actorUser.getId(), actorUser.getNickname(), postQueryDto.roomId(), postQueryDto.page(), postQueryDto.postId(), postQueryDto.postType()); + } + } } From 727ed358845cf1577c7292482f87ff26f4689847 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 01:30:35 +0900 Subject: [PATCH 43/93] =?UTF-8?q?[chore]=20=EC=A3=BC=EC=84=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/message/application/port/out/RoomEventCommandPort.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java b/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java index 987984220..64446d3b6 100644 --- a/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java +++ b/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java @@ -32,6 +32,7 @@ void publishRoomCommentLikedEvent(Long targetUserId, Long actorUserId, String ac void publishRoomPostLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, Long roomId, Integer page, Long postId, String postType); + // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ์˜ ๋‚˜์˜ ๋Œ“๊ธ€์— ๋Œ€๋Œ“๊ธ€์ด ๋‹ฌ๋ฆฐ ๊ฒฝ์šฐ void publicRoomPostCommentRepliedEvent(Long targetUserId, Long actorUserId, String actorUsername, Long roomId, Integer page, Long postId, String postType); } \ No newline at end of file From 6e5b56c218b56e27f9268e90b3738b35aa718976 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 01:34:51 +0900 Subject: [PATCH 44/93] =?UTF-8?q?[refactor]=20=EC=9D=B4=EB=B2=A4=ED=8A=B8?= =?UTF-8?q?=20adapter=20=EB=B3=80=EC=88=98=EB=AA=85=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/out/event/RoomEventPublisherAdapter.java | 10 +++++----- .../application/port/out/RoomEventCommandPort.java | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/konkuk/thip/message/adapter/out/event/RoomEventPublisherAdapter.java b/src/main/java/konkuk/thip/message/adapter/out/event/RoomEventPublisherAdapter.java index 8c46e60f3..6cb1ef443 100644 --- a/src/main/java/konkuk/thip/message/adapter/out/event/RoomEventPublisherAdapter.java +++ b/src/main/java/konkuk/thip/message/adapter/out/event/RoomEventPublisherAdapter.java @@ -71,14 +71,14 @@ public void publishRoomActivityStartedEvent(Long targetUserId, Long roomId, Stri } @Override - public void publishRoomJoinEventToHost(Long ownerUserId, Long roomId, String roomTitle, - Long applicantUserId, String applicantUsername) { + public void publishRoomJoinEventToHost(Long hostUserId, Long roomId, String roomTitle, + Long actorUserId, String actorUsername) { publisher.publishEvent(RoomEvents.RoomJoinRequestedToOwnerEvent.builder() - .ownerUserId(ownerUserId) + .ownerUserId(hostUserId) .roomId(roomId) .roomTitle(roomTitle) - .applicantUserId(applicantUserId) - .applicantUsername(applicantUsername) + .applicantUserId(actorUserId) + .applicantUsername(actorUsername) .build()); } diff --git a/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java b/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java index 64446d3b6..1c7dcd7a6 100644 --- a/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java +++ b/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java @@ -21,8 +21,8 @@ void publishRoomRecordCreatedEvent(Long targetUserId, Long actorUserId, String a void publishRoomActivityStartedEvent(Long targetUserId, Long roomId, String roomTitle); // ๋‚ด๊ฐ€ ๋ฐฉ์žฅ์ผ ๋•Œ, ์ƒˆ๋กœ์šด ์‚ฌ์šฉ์ž๊ฐ€ ๋ชจ์ž„๋ฐฉ ์ฐธ์—ฌ๋ฅผ ํ•œ ๊ฒฝ์šฐ - void publishRoomJoinEventToHost(Long ownerUserId, Long roomId, String roomTitle, - Long applicantUserId, String applicantUsername); + void publishRoomJoinEventToHost(Long hostUserId, Long roomId, String roomTitle, + Long actorUserId, String actorUsername); // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ์˜ ๋‚˜์˜ ๋Œ“๊ธ€์ด ์ข‹์•„์š”๋ฅผ ๋ฐ›๋Š” ๊ฒฝ์šฐ void publishRoomCommentLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, From 2ab23c8eeabfa73362eca8a7ab4ab4b92d112fca Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 01:36:26 +0900 Subject: [PATCH 45/93] =?UTF-8?q?[feat]=20=EB=B0=A9=20=EC=B0=B8=EC=97=AC?= =?UTF-8?q?=20=ED=91=B8=EC=89=AC=EC=95=8C=EB=A6=BC=20=EC=A0=84=EC=86=A1=20?= =?UTF-8?q?=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EB=B0=9C=ED=96=89=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RoomParticipantCommandPersistenceAdapter.java | 9 +++++++++ .../RoomParticipantJpaRepository.java | 4 ++++ .../port/out/RoomParticipantCommandPort.java | 2 ++ .../room/application/service/RoomJoinService.java | 15 +++++++++++++++ 4 files changed, 30 insertions(+) diff --git a/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomParticipantCommandPersistenceAdapter.java b/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomParticipantCommandPersistenceAdapter.java index 620cbbaec..44bbd3666 100644 --- a/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomParticipantCommandPersistenceAdapter.java +++ b/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomParticipantCommandPersistenceAdapter.java @@ -70,6 +70,15 @@ public void update(RoomParticipant roomParticipant) { roomParticipantJpaRepository.save(roomParticipantJpaEntity); } + @Override + public RoomParticipant findHostByRoomId(Long roomId) { + RoomParticipantJpaEntity roomParticipantJpaEntity = roomParticipantJpaRepository.findHostByRoomId(roomId).orElseThrow( + () -> new EntityNotFoundException(ErrorCode.ROOM_PARTICIPANT_NOT_FOUND) + ); + + return roomParticipantMapper.toDomainEntity(roomParticipantJpaEntity); + } + @Override public Optional findByUserIdAndRoomIdOptional(Long userId, Long roomId) { return roomParticipantJpaRepository.findByUserIdAndRoomId(userId, roomId) diff --git a/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/roomparticipant/RoomParticipantJpaRepository.java b/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/roomparticipant/RoomParticipantJpaRepository.java index 22284a4d6..1dfe434d3 100644 --- a/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/roomparticipant/RoomParticipantJpaRepository.java +++ b/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/roomparticipant/RoomParticipantJpaRepository.java @@ -30,4 +30,8 @@ public interface RoomParticipantJpaRepository extends JpaRepository findHostByRoomId(Long roomId); } diff --git a/src/main/java/konkuk/thip/room/application/port/out/RoomParticipantCommandPort.java b/src/main/java/konkuk/thip/room/application/port/out/RoomParticipantCommandPort.java index 519a66e43..b26d09f6d 100644 --- a/src/main/java/konkuk/thip/room/application/port/out/RoomParticipantCommandPort.java +++ b/src/main/java/konkuk/thip/room/application/port/out/RoomParticipantCommandPort.java @@ -24,4 +24,6 @@ default RoomParticipant getByUserIdAndRoomIdOrThrow(Long userId, Long roomId) { void deleteByUserIdAndRoomId(Long userId, Long roomId); void update(RoomParticipant roomParticipant); + + RoomParticipant findHostByRoomId(Long roomId); } diff --git a/src/main/java/konkuk/thip/room/application/service/RoomJoinService.java b/src/main/java/konkuk/thip/room/application/service/RoomJoinService.java index 619a3c43d..ca11ca1dd 100644 --- a/src/main/java/konkuk/thip/room/application/service/RoomJoinService.java +++ b/src/main/java/konkuk/thip/room/application/service/RoomJoinService.java @@ -2,6 +2,7 @@ import konkuk.thip.common.exception.BusinessException; import konkuk.thip.common.exception.code.ErrorCode; +import konkuk.thip.message.application.port.out.RoomEventCommandPort; import konkuk.thip.room.application.port.in.RoomJoinUseCase; import konkuk.thip.room.application.port.in.dto.RoomJoinCommand; import konkuk.thip.room.application.port.in.dto.RoomJoinResult; @@ -10,6 +11,8 @@ import konkuk.thip.room.domain.Room; import konkuk.thip.room.application.port.in.dto.RoomJoinType; import konkuk.thip.room.domain.RoomParticipant; +import konkuk.thip.user.application.port.out.UserCommandPort; +import konkuk.thip.user.domain.User; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -22,6 +25,9 @@ public class RoomJoinService implements RoomJoinUseCase { private final RoomCommandPort roomCommandPort; private final RoomParticipantCommandPort roomParticipantCommandPort; + private final UserCommandPort userCommandPort; + + private final RoomEventCommandPort roomEventCommandPort; @Override @Transactional @@ -45,9 +51,18 @@ public RoomJoinResult changeJoinState(RoomJoinCommand roomJoinCommand) { // ๋ฐฉ์˜ ์ƒํƒœ ์—…๋ฐ์ดํŠธ roomCommandPort.update(room); + // ์ฐธ์—ฌ์ž ํ‘ธ์‰ฌ ์•Œ๋ฆผ ์ „์†ก (ํ˜ธ์ŠคํŠธ์—๊ฒŒ๋งŒ ์ „์†ก) + sendNotifications(roomJoinCommand, room); + return RoomJoinResult.of(room.getId(), type.getType()); } + private void sendNotifications(RoomJoinCommand roomJoinCommand, Room room) { + RoomParticipant targetUser = roomParticipantCommandPort.findHostByRoomId(room.getId()); + User actorUser = userCommandPort.findById(roomJoinCommand.userId()); + roomEventCommandPort.publishRoomJoinEventToHost(targetUser.getUserId(), room.getId(), room.getTitle(), actorUser.getId(), actorUser.getNickname()); + } + private void handleCancel(RoomJoinCommand roomJoinCommand, Optional participantOptional, Optional roomParticipantOptional, Room room) { // ์ฐธ์—ฌํ•˜์ง€ ์•Š์€ ์ƒํƒœ RoomParticipant participant = participantOptional.orElseThrow(() -> From 20d169b8a0c03dda33ff82f6509fa67258808efa Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 02:07:15 +0900 Subject: [PATCH 46/93] =?UTF-8?q?[feat]=20=EB=B0=A9=20=EC=83=81=ED=83=9C?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=20=EC=8A=A4=EC=BC=80=EC=A4=84=EB=9F=AC=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98=20=EB=B0=8F=20=EB=B0=A9=20=EB=AA=A8=EC=9E=84?= =?UTF-8?q?=EB=B0=A9=20=ED=99=9C=EB=8F=99=20=EC=8B=9C=EC=9E=91=20=ED=91=B8?= =?UTF-8?q?=EC=89=AC=EC=95=8C=EB=A6=BC=20=EC=A0=84=EC=86=A1=20=EC=9D=B4?= =?UTF-8?q?=EB=B2=A4=ED=8A=B8=20=EB=B0=9C=ED=96=89=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/scheduler/RoomStateScheduler.java | 24 ++++++++ .../RoomCommandPersistenceAdapter.java | 20 ++++++ .../repository/RoomJpaRepository.java | 38 ++++++++++++ .../port/in/RoomStateChangeUseCase.java | 6 ++ .../application/port/out/RoomCommandPort.java | 8 +++ .../service/RoomStateChangeService.java | 61 +++++++++++++++++++ 6 files changed, 157 insertions(+) create mode 100644 src/main/java/konkuk/thip/common/scheduler/RoomStateScheduler.java create mode 100644 src/main/java/konkuk/thip/room/application/port/in/RoomStateChangeUseCase.java create mode 100644 src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java diff --git a/src/main/java/konkuk/thip/common/scheduler/RoomStateScheduler.java b/src/main/java/konkuk/thip/common/scheduler/RoomStateScheduler.java new file mode 100644 index 000000000..ed71adeb8 --- /dev/null +++ b/src/main/java/konkuk/thip/common/scheduler/RoomStateScheduler.java @@ -0,0 +1,24 @@ +package konkuk.thip.common.scheduler; + +import konkuk.thip.room.application.port.in.RoomStateChangeUseCase; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +@RequiredArgsConstructor +public class RoomStateScheduler { + + private final RoomStateChangeUseCase roomStateChangeUseCase; + + // ๋งค์ผ ์ž์ • ์‹คํ–‰ + @Scheduled(cron = "0 0 0 * * *", zone = "Asia/Seoul") + public void changeRoomState() { + log.info("[์Šค์ผ€์ค„๋Ÿฌ] ๋ฐฉ ์ƒํƒœ ๋ณ€๊ฒฝ ์‹œ์ž‘"); + roomStateChangeUseCase.changeRoomStateToExpired(); + roomStateChangeUseCase.changeRoomStateToProgress(); + log.info("[์Šค์ผ€์ค„๋Ÿฌ] ๋ฐฉ ์ƒํƒœ ๋ณ€๊ฒฝ ์™„๋ฃŒ"); + } +} diff --git a/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomCommandPersistenceAdapter.java b/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomCommandPersistenceAdapter.java index 3a93b11f9..c9486a9b2 100644 --- a/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomCommandPersistenceAdapter.java +++ b/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomCommandPersistenceAdapter.java @@ -4,6 +4,7 @@ import konkuk.thip.book.adapter.out.persistence.repository.BookJpaRepository; import konkuk.thip.common.exception.EntityNotFoundException; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; +import konkuk.thip.room.adapter.out.jpa.RoomStatus; import konkuk.thip.room.adapter.out.mapper.RoomMapper; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.application.port.out.RoomCommandPort; @@ -11,6 +12,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; +import java.util.List; import java.util.Optional; import static konkuk.thip.common.exception.code.ErrorCode.*; @@ -56,4 +58,22 @@ public void update(Room room) { roomJpaRepository.save(roomJpaEntity.updateFrom(room)); } + + @Override + public int updateRoomStateToExpired(RoomStatus exceptStatus) { + return roomJpaRepository.updateRoomStatusToExpired(exceptStatus); + } + + @Override + public int updateRoomStateToInProgress(RoomStatus roomStatus) { + return roomJpaRepository.updateRoomStatusToInProgress(roomStatus); + } + + @Override + public List findProgressTargetRooms(RoomStatus status) { + List roomJpaEntities = roomJpaRepository.findProgressTargetIds(status); + return roomJpaEntities.stream() + .map(roomMapper::toDomainEntity) + .toList(); + } } diff --git a/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/RoomJpaRepository.java b/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/RoomJpaRepository.java index cf88790eb..448e32eaf 100644 --- a/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/RoomJpaRepository.java +++ b/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/RoomJpaRepository.java @@ -1,11 +1,14 @@ package konkuk.thip.room.adapter.out.persistence.repository; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; +import konkuk.thip.room.adapter.out.jpa.RoomStatus; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import java.time.LocalDate; +import java.util.List; import java.util.Optional; public interface RoomJpaRepository extends JpaRepository, RoomQueryRepository { @@ -20,4 +23,39 @@ public interface RoomJpaRepository extends JpaRepository, R "AND r.startDate > :currentDate") int countActiveRoomsByBookIdAndStartDateAfter(@Param("isbn") String isbn, @Param("currentDate") LocalDate currentDate); + /** + * end_date < ์˜ค๋Š˜ => EXPIRED + * ์ด๋ฏธ EXPIRED ์ธ ๊ฒƒ์€ ์ œ์™ธ + */ + @Modifying(clearAutomatically = true, flushAutomatically = true) + @Query(""" + update RoomJpaEntity r + set r.roomStatus = :status + where r.endDate < current_date + and r.roomStatus <> :exceptStatus + """) + int updateRoomStatusToExpired(RoomStatus exceptStatus); + + /** + * start_date <= ์˜ค๋Š˜ AND end_date >= ์˜ค๋Š˜ => IN_PROGRESS + * RECRUITING ์ธ ๊ฒƒ๋งŒ ๋Œ€์ƒ + */ + @Modifying(clearAutomatically = true, flushAutomatically = true) + @Query(""" + update RoomJpaEntity r + set r.roomStatus = :status + where r.startDate <= current_date + and r.endDate >= current_date + and r.roomStatus = :status + """) + int updateRoomStatusToInProgress(RoomStatus status); + + @Query(""" + select r + from RoomJpaEntity r + where r.startDate <= current_date + and r.endDate >= current_date + and r.roomStatus = :status + """) + List findProgressTargetIds(RoomStatus status); } diff --git a/src/main/java/konkuk/thip/room/application/port/in/RoomStateChangeUseCase.java b/src/main/java/konkuk/thip/room/application/port/in/RoomStateChangeUseCase.java new file mode 100644 index 000000000..b826f2096 --- /dev/null +++ b/src/main/java/konkuk/thip/room/application/port/in/RoomStateChangeUseCase.java @@ -0,0 +1,6 @@ +package konkuk.thip.room.application.port.in; + +public interface RoomStateChangeUseCase { + void changeRoomStateToExpired(); + void changeRoomStateToProgress(); +} diff --git a/src/main/java/konkuk/thip/room/application/port/out/RoomCommandPort.java b/src/main/java/konkuk/thip/room/application/port/out/RoomCommandPort.java index bbc98a6a9..e48a07664 100644 --- a/src/main/java/konkuk/thip/room/application/port/out/RoomCommandPort.java +++ b/src/main/java/konkuk/thip/room/application/port/out/RoomCommandPort.java @@ -1,8 +1,10 @@ package konkuk.thip.room.application.port.out; import konkuk.thip.common.exception.EntityNotFoundException; +import konkuk.thip.room.adapter.out.jpa.RoomStatus; import konkuk.thip.room.domain.Room; +import java.util.List; import java.util.Optional; import static konkuk.thip.common.exception.code.ErrorCode.ROOM_NOT_FOUND; @@ -19,4 +21,10 @@ default Room getByIdOrThrow(Long id) { Long save(Room room); void update(Room room); + + int updateRoomStateToExpired(RoomStatus exceptStatus); + + int updateRoomStateToInProgress(RoomStatus roomStatus); + + List findProgressTargetRooms(RoomStatus status); } diff --git a/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java b/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java new file mode 100644 index 000000000..a046a674d --- /dev/null +++ b/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java @@ -0,0 +1,61 @@ +package konkuk.thip.room.application.service; + +import konkuk.thip.message.application.port.out.RoomEventCommandPort; +import konkuk.thip.room.adapter.out.jpa.RoomStatus; +import konkuk.thip.room.application.port.in.RoomStateChangeUseCase; +import konkuk.thip.room.application.port.out.RoomCommandPort; +import konkuk.thip.room.application.port.out.RoomParticipantCommandPort; +import konkuk.thip.room.domain.Room; +import konkuk.thip.room.domain.RoomParticipant; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Slf4j +@Service +@RequiredArgsConstructor +public class RoomStateChangeService implements RoomStateChangeUseCase { + + private final RoomCommandPort roomCommandPort; + private final RoomParticipantCommandPort roomParticipantCommandPort; + + private final RoomEventCommandPort roomEventCommandPort; + + /** + * end_date < ์˜ค๋Š˜ => EXPIRED + */ + @Async + @Override + @Transactional + public void changeRoomStateToExpired() { + int updated = roomCommandPort.updateRoomStateToExpired(RoomStatus.EXPIRED); + log.info("[RoomState] EXPIRED๋กœ ๋ณ€๊ฒฝ๋œ ๊ฑด์ˆ˜={}", updated); + } + + /** + * start_date <= ์˜ค๋Š˜ AND end_date >= ์˜ค๋Š˜ => IN_PROGRESS + */ + @Override + @Transactional + public void changeRoomStateToProgress() { + // ๋ฐฉ ๋ชจ์ž„๋ฐฉ ํ™œ๋™ ์‹œ์ž‘ ํ‘ธ์‰ฌ์•Œ๋ฆผ ์ „์†ก + sendNotifications(); + + int updated = roomCommandPort.updateRoomStateToInProgress(RoomStatus.RECRUITING); + log.info("[RoomState] IN_PROGRESS๋กœ ๋ณ€๊ฒฝ๋œ ๊ฑด์ˆ˜={}", updated); + } + + private void sendNotifications() { + List targetRooms = roomCommandPort.findProgressTargetRooms(RoomStatus.RECRUITING); + for (Room room : targetRooms) { + List targetUsers = roomParticipantCommandPort.findAllByRoomId(room.getId()); + for (RoomParticipant participant : targetUsers) { + roomEventCommandPort.publishRoomActivityStartedEvent(participant.getId(), room.getId(), room.getTitle()); + } + } + } +} From 796889871c50b4793e6d931842c25584f8d627a9 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 02:19:36 +0900 Subject: [PATCH 47/93] =?UTF-8?q?[feat]=20=EA=B8=B0=EB=A1=9D/=ED=88=AC?= =?UTF-8?q?=ED=91=9C=20=EC=83=9D=EC=84=B1=20=ED=91=B8=EC=89=AC=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EC=A0=84=EC=86=A1=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EB=B0=9C=ED=96=89=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/RecordCreateService.java | 20 +++++++++++++++++++ .../service/VoteCreateService.java | 16 ++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/main/java/konkuk/thip/roompost/application/service/RecordCreateService.java b/src/main/java/konkuk/thip/roompost/application/service/RecordCreateService.java index e3224f6f6..7e075f9cf 100644 --- a/src/main/java/konkuk/thip/roompost/application/service/RecordCreateService.java +++ b/src/main/java/konkuk/thip/roompost/application/service/RecordCreateService.java @@ -3,6 +3,7 @@ import konkuk.thip.book.application.port.out.BookCommandPort; import konkuk.thip.book.domain.Book; import konkuk.thip.common.exception.BusinessException; +import konkuk.thip.message.application.port.out.RoomEventCommandPort; import konkuk.thip.roompost.application.port.in.RecordCreateUseCase; import konkuk.thip.roompost.application.port.in.dto.record.RecordCreateCommand; import konkuk.thip.roompost.application.port.in.dto.record.RecordCreateResult; @@ -14,10 +15,14 @@ import konkuk.thip.room.domain.Room; import konkuk.thip.room.domain.RoomParticipant; import konkuk.thip.roompost.application.service.manager.RoomProgressManager; +import konkuk.thip.user.application.port.out.UserCommandPort; +import konkuk.thip.user.domain.User; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; + import static konkuk.thip.common.exception.code.ErrorCode.RECORD_CANNOT_BE_OVERVIEW; @Service @@ -28,10 +33,13 @@ public class RecordCreateService implements RecordCreateUseCase { private final RoomCommandPort roomCommandPort; private final BookCommandPort bookCommandPort; private final RoomParticipantCommandPort roomParticipantCommandPort; + private final UserCommandPort userCommandPort; private final RoomParticipantValidator roomParticipantValidator; private final RoomProgressManager roomProgressManager; + private final RoomEventCommandPort roomEventCommandPort; + @Override @Transactional //todo updateRoomPercentage ์Šค์ผ€์ค„๋Ÿฌ๋กœ ์ฑ…์ž„์„ ๋ถ„๋ฆฌํ• ์ง€ ๋…ผ์˜ @@ -63,9 +71,21 @@ public RecordCreateResult createRecord(RecordCreateCommand command) { // 5. RoomParticipant, Room progress ์ •๋ณด update roomProgressManager.updateUserAndRoomProgress(roomParticipant, room, book, record.getPage()); + // 6. ๋ชจ์ž„๋ฐฉ ์ฐธ์—ฌ์ž๋“ค์—๊ฒŒ ๊ธฐ๋ก ์ƒ์„ฑ ์•Œ๋ฆผ ์ „์†ก (๋ณธ์ธ ์ œ์™ธ) + sendNotifications(command, room, record, newRecordId); + return RecordCreateResult.of(newRecordId, command.roomId()); } + private void sendNotifications(RecordCreateCommand command, Room room, Record record, Long newRecordId) { + User actorUser = userCommandPort.findById(command.userId()); + List targetUsers = roomParticipantCommandPort.findAllByRoomId(command.roomId()); + for (RoomParticipant targetUser : targetUsers) { + if (targetUser.getUserId().equals(command.userId())) continue; // ๋ณธ์ธ ์ œ์™ธ + roomEventCommandPort.publishRoomRecordCreatedEvent(targetUser.getUserId(), actorUser.getId(), actorUser.getNickname(), room.getId(), room.getTitle(), record.getPage(), newRecordId); + } + } + private void validateRoomParticipant(RoomParticipant roomParticipant, boolean isOverview) { // UserRoom์˜ ์ดํ‰ ์ž‘์„ฑ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ๊ฒ€์ฆ if (!roomParticipant.canWriteOverview() && isOverview) { diff --git a/src/main/java/konkuk/thip/roompost/application/service/VoteCreateService.java b/src/main/java/konkuk/thip/roompost/application/service/VoteCreateService.java index f7098d6be..ce7cf3788 100644 --- a/src/main/java/konkuk/thip/roompost/application/service/VoteCreateService.java +++ b/src/main/java/konkuk/thip/roompost/application/service/VoteCreateService.java @@ -2,16 +2,17 @@ import konkuk.thip.book.application.port.out.BookCommandPort; import konkuk.thip.book.domain.Book; +import konkuk.thip.message.application.port.out.RoomEventCommandPort; import konkuk.thip.room.application.port.out.RoomCommandPort; import konkuk.thip.room.application.port.out.RoomParticipantCommandPort; import konkuk.thip.room.application.service.validator.RoomParticipantValidator; import konkuk.thip.room.domain.Room; import konkuk.thip.room.domain.RoomParticipant; -import konkuk.thip.roompost.application.service.manager.RoomProgressManager; import konkuk.thip.roompost.application.port.in.VoteCreateUseCase; import konkuk.thip.roompost.application.port.in.dto.vote.VoteCreateCommand; import konkuk.thip.roompost.application.port.in.dto.vote.VoteCreateResult; import konkuk.thip.roompost.application.port.out.VoteCommandPort; +import konkuk.thip.roompost.application.service.manager.RoomProgressManager; import konkuk.thip.roompost.domain.Vote; import konkuk.thip.roompost.domain.VoteItem; import lombok.RequiredArgsConstructor; @@ -34,6 +35,8 @@ public class VoteCreateService implements VoteCreateUseCase { private final RoomProgressManager roomProgressManager; + private final RoomEventCommandPort roomEventCommandPort; + @Transactional @Override public VoteCreateResult createVote(VoteCreateCommand command) { @@ -68,9 +71,20 @@ public VoteCreateResult createVote(VoteCreateCommand command) { // 4. RoomParticipant, Room progress ์ •๋ณด update roomProgressManager.updateUserAndRoomProgress(roomParticipant, room, book, vote.getPage()); + // 5. ๋ชจ์ž„๋ฐฉ ์ฐธ์—ฌ์ž๋“ค์—๊ฒŒ ํˆฌํ‘œ ์ƒ์„ฑ ์•Œ๋ฆผ ์ „์†ก (๋ณธ์ธ ์ œ์™ธ) + sendNotifications(command, room, vote, savedVoteId); + return VoteCreateResult.of(savedVoteId, command.roomId()); } + private void sendNotifications(VoteCreateCommand command, Room room, Vote vote, Long newVoteId) { + List targetUsers = roomParticipantCommandPort.findAllByRoomId(command.roomId()); + for (RoomParticipant targetUser : targetUsers) { + if (targetUser.getUserId().equals(command.userId())) continue; // ๋ณธ์ธ ์ œ์™ธ + roomEventCommandPort.publishRoomVoteStartedEvent(targetUser.getUserId(), room.getId(), room.getTitle(), vote.getPage(), newVoteId); + } + } + private void validateVote(Vote vote, Book book) { // ํŽ˜์ด์ง€ ์œ ํšจ์„ฑ ๊ฒ€์ฆ vote.validatePage(book.getPageCount()); From 8528cdc345e5ce111f1d542322903992064bc05e Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 02:33:36 +0900 Subject: [PATCH 48/93] =?UTF-8?q?[fix]=20=EC=9E=98=EB=AA=BB=EB=90=9C=20?= =?UTF-8?q?=ED=8C=94=EB=A1=9C=EC=9B=8C=20=EC=A1=B0=ED=9A=8C=20=EC=BF=BC?= =?UTF-8?q?=EB=A6=AC=20=EC=88=98=EC=A0=95=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feed/application/service/FeedCreateService.java | 6 +++--- .../persistence/FollowingQueryPersistenceAdapter.java | 10 ++-------- .../out/persistence/UserQueryPersistenceAdapter.java | 10 ++++++++++ .../out/persistence/repository/UserJpaRepository.java | 5 +++++ .../repository/following/FollowingJpaRepository.java | 6 ------ .../user/application/port/out/FollowingQueryPort.java | 3 --- .../thip/user/application/port/out/UserQueryPort.java | 4 +++- 7 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/main/java/konkuk/thip/feed/application/service/FeedCreateService.java b/src/main/java/konkuk/thip/feed/application/service/FeedCreateService.java index bc6e2f1d0..ba109a388 100644 --- a/src/main/java/konkuk/thip/feed/application/service/FeedCreateService.java +++ b/src/main/java/konkuk/thip/feed/application/service/FeedCreateService.java @@ -13,8 +13,8 @@ import konkuk.thip.feed.domain.value.Tag; import konkuk.thip.feed.domain.value.TagList; import konkuk.thip.message.application.port.out.FeedEventCommandPort; -import konkuk.thip.user.application.port.out.FollowingQueryPort; import konkuk.thip.user.application.port.out.UserCommandPort; +import konkuk.thip.user.application.port.out.UserQueryPort; import konkuk.thip.user.domain.User; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -29,7 +29,7 @@ public class FeedCreateService implements FeedCreateUseCase { private final BookCommandPort bookCommandPort; private final FeedCommandPort feedCommandPort; private final BookApiQueryPort bookApiQueryPort; - private final FollowingQueryPort followingQueryPort; + private final UserQueryPort userQueryPort; private final UserCommandPort userCommandPort; private final ImageUrlValidationService imageUrlValidationService; @@ -65,7 +65,7 @@ public Long createFeed(FeedCreateCommand command) { } private void sendNotifications(FeedCreateCommand command, Feed feed) { - List targetUsers = followingQueryPort.getAllFollowersByUserId(command.userId()); + List targetUsers = userQueryPort.getAllFollowersByUserId(command.userId()); User actorUser = userCommandPort.findById(command.userId()); for (User targetUser : targetUsers) { feedEventCommandPort.publishFolloweeNewPostEvent(targetUser.getId(), actorUser.getId(), actorUser.getNickname(), feed.getId()); diff --git a/src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingQueryPersistenceAdapter.java b/src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingQueryPersistenceAdapter.java index 06182fd8a..bff694526 100644 --- a/src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingQueryPersistenceAdapter.java +++ b/src/main/java/konkuk/thip/user/adapter/out/persistence/FollowingQueryPersistenceAdapter.java @@ -3,11 +3,10 @@ import konkuk.thip.common.util.CursorBasedList; import konkuk.thip.common.util.DateUtil; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; -import konkuk.thip.user.application.port.out.dto.FollowingQueryDto; -import konkuk.thip.user.application.port.out.dto.UserQueryDto; import konkuk.thip.user.adapter.out.persistence.repository.following.FollowingJpaRepository; import konkuk.thip.user.application.port.out.FollowingQueryPort; -import konkuk.thip.user.domain.User; +import konkuk.thip.user.application.port.out.dto.FollowingQueryDto; +import konkuk.thip.user.application.port.out.dto.UserQueryDto; import konkuk.thip.user.domain.value.Alias; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; @@ -67,9 +66,4 @@ public int getFollowingCountByUser(Long userId) { public List findAllFollowingUsersOrderByFollowedAtDesc(Long userId) { return followingJpaRepository.findAllFollowingUsersOrderByFollowedAtDesc(userId); } - - @Override - public List getAllFollowersByUserId(Long userId) { - return followingJpaRepository.findAllFollowersByUserId(userId); - } } diff --git a/src/main/java/konkuk/thip/user/adapter/out/persistence/UserQueryPersistenceAdapter.java b/src/main/java/konkuk/thip/user/adapter/out/persistence/UserQueryPersistenceAdapter.java index d95bce510..8e4535ece 100644 --- a/src/main/java/konkuk/thip/user/adapter/out/persistence/UserQueryPersistenceAdapter.java +++ b/src/main/java/konkuk/thip/user/adapter/out/persistence/UserQueryPersistenceAdapter.java @@ -2,11 +2,13 @@ import konkuk.thip.common.util.Cursor; import konkuk.thip.common.util.CursorBasedList; +import konkuk.thip.user.adapter.out.mapper.UserMapper; import konkuk.thip.user.adapter.out.persistence.function.ReactionQueryFunction; import konkuk.thip.user.application.port.out.dto.ReactionQueryDto; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import konkuk.thip.user.application.port.out.UserQueryPort; import konkuk.thip.user.application.port.out.dto.UserQueryDto; +import konkuk.thip.user.domain.User; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; @@ -19,6 +21,7 @@ public class UserQueryPersistenceAdapter implements UserQueryPort { private final UserJpaRepository userJpaRepository; + private final UserMapper userMapper; @Override public boolean existsByNickname(String nickname) { @@ -66,6 +69,13 @@ public CursorBasedList findBothReactionsByUserId(Long userId, ); } + @Override + public List getAllFollowersByUserId(Long userId) { + return userJpaRepository.findAllFollowersByUserId(userId).stream() + .map(userMapper::toDomainEntity) + .toList(); + } + private CursorBasedList getReactions(Long userId, Cursor cursor, ReactionQueryFunction reactionQueryFunction) { LocalDateTime cursorLocalDateTime = cursor.isFirstRequest() ? null : cursor.getLocalDateTime(0); diff --git a/src/main/java/konkuk/thip/user/adapter/out/persistence/repository/UserJpaRepository.java b/src/main/java/konkuk/thip/user/adapter/out/persistence/repository/UserJpaRepository.java index 214ea6009..7e2f81c4a 100644 --- a/src/main/java/konkuk/thip/user/adapter/out/persistence/repository/UserJpaRepository.java +++ b/src/main/java/konkuk/thip/user/adapter/out/persistence/repository/UserJpaRepository.java @@ -2,7 +2,9 @@ import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import java.util.List; import java.util.Optional; public interface UserJpaRepository extends JpaRepository, UserQueryRepository { @@ -19,4 +21,7 @@ public interface UserJpaRepository extends JpaRepository, U boolean existsByNicknameAndUserIdNot(String nickname, Long userId); boolean existsByOauth2Id(String oauth2Id); + + @Query("SELECT f.userJpaEntity FROM FollowingJpaEntity f WHERE f.followingUserJpaEntity.userId = :userId") + List findAllFollowersByUserId(Long userId); } diff --git a/src/main/java/konkuk/thip/user/adapter/out/persistence/repository/following/FollowingJpaRepository.java b/src/main/java/konkuk/thip/user/adapter/out/persistence/repository/following/FollowingJpaRepository.java index 584e4d420..0ceae15ab 100644 --- a/src/main/java/konkuk/thip/user/adapter/out/persistence/repository/following/FollowingJpaRepository.java +++ b/src/main/java/konkuk/thip/user/adapter/out/persistence/repository/following/FollowingJpaRepository.java @@ -1,13 +1,10 @@ package konkuk.thip.user.adapter.out.persistence.repository.following; import konkuk.thip.user.adapter.out.jpa.FollowingJpaEntity; -import konkuk.thip.user.domain.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; -import java.util.List; - @Repository public interface FollowingJpaRepository extends JpaRepository, FollowingQueryRepository { @@ -16,7 +13,4 @@ public interface FollowingJpaRepository extends JpaRepository findAllFollowersByUserId(Long userId); } diff --git a/src/main/java/konkuk/thip/user/application/port/out/FollowingQueryPort.java b/src/main/java/konkuk/thip/user/application/port/out/FollowingQueryPort.java index 8b540d09f..3597d83c0 100644 --- a/src/main/java/konkuk/thip/user/application/port/out/FollowingQueryPort.java +++ b/src/main/java/konkuk/thip/user/application/port/out/FollowingQueryPort.java @@ -3,7 +3,6 @@ import konkuk.thip.common.util.CursorBasedList; import konkuk.thip.user.application.port.out.dto.FollowingQueryDto; import konkuk.thip.user.application.port.out.dto.UserQueryDto; -import konkuk.thip.user.domain.User; import java.util.List; @@ -21,7 +20,5 @@ public interface FollowingQueryPort { * user๊ฐ€ ํŒ”๋กœ์ž‰ํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์„ ์กฐํšŒ */ List findAllFollowingUsersOrderByFollowedAtDesc(Long userId); - - List getAllFollowersByUserId(Long userId); } diff --git a/src/main/java/konkuk/thip/user/application/port/out/UserQueryPort.java b/src/main/java/konkuk/thip/user/application/port/out/UserQueryPort.java index 29be62336..3e6de1cdd 100644 --- a/src/main/java/konkuk/thip/user/application/port/out/UserQueryPort.java +++ b/src/main/java/konkuk/thip/user/application/port/out/UserQueryPort.java @@ -3,8 +3,8 @@ import konkuk.thip.common.util.Cursor; import konkuk.thip.common.util.CursorBasedList; import konkuk.thip.user.application.port.out.dto.ReactionQueryDto; -import konkuk.thip.user.application.port.in.dto.UserViewAliasChoiceResult; import konkuk.thip.user.application.port.out.dto.UserQueryDto; +import konkuk.thip.user.domain.User; import java.util.List; import java.util.Set; @@ -25,4 +25,6 @@ public interface UserQueryPort { CursorBasedList findCommentReactionsByUserId(Long userId, Cursor cursor, String label); CursorBasedList findBothReactionsByUserId(Long userId, Cursor cursor, String likeLabel, String commentLabel); + + List getAllFollowersByUserId(Long userId); } From a1ffc47b174cb4c7bae2cddd6730bde07adcc00b Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 02:46:49 +0900 Subject: [PATCH 49/93] =?UTF-8?q?[fix]=20=EB=8B=A8=EC=9C=84=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/RoomJoinServiceTest.java | 24 ++++++++++++++++++- .../service/UserFollowServiceTest.java | 7 +++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/test/java/konkuk/thip/room/application/service/RoomJoinServiceTest.java b/src/test/java/konkuk/thip/room/application/service/RoomJoinServiceTest.java index c94bedfe6..383d0933d 100644 --- a/src/test/java/konkuk/thip/room/application/service/RoomJoinServiceTest.java +++ b/src/test/java/konkuk/thip/room/application/service/RoomJoinServiceTest.java @@ -2,17 +2,22 @@ import konkuk.thip.common.exception.BusinessException; import konkuk.thip.common.exception.code.ErrorCode; +import konkuk.thip.message.application.port.out.RoomEventCommandPort; import konkuk.thip.room.application.port.in.dto.RoomJoinCommand; import konkuk.thip.room.application.port.out.RoomCommandPort; import konkuk.thip.room.application.port.out.RoomParticipantCommandPort; import konkuk.thip.room.domain.Room; import konkuk.thip.room.domain.RoomParticipant; +import konkuk.thip.user.application.port.out.UserCommandPort; +import konkuk.thip.user.domain.User; +import konkuk.thip.user.domain.value.Alias; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import java.time.LocalDate; +import java.util.List; import java.util.Optional; import static konkuk.thip.room.application.port.in.dto.RoomJoinType.CANCEL; @@ -26,6 +31,8 @@ class RoomJoinServiceTest { private RoomCommandPort roomCommandPort; private RoomParticipantCommandPort roomParticipantCommandPort; private RoomJoinService roomJoinService; + private UserCommandPort userCommandPort; + private RoomEventCommandPort roomEventCommandPort; private final Long ROOM_ID = 1L; private final Long USER_ID = 2L; @@ -38,10 +45,14 @@ class RoomJoinServiceTest { void setUp() { roomCommandPort = mock(RoomCommandPort.class); roomParticipantCommandPort = mock(RoomParticipantCommandPort.class); + userCommandPort = mock(UserCommandPort.class); + roomEventCommandPort = mock(RoomEventCommandPort.class); roomJoinService = new RoomJoinService( roomCommandPort, - roomParticipantCommandPort + roomParticipantCommandPort, + userCommandPort, + roomEventCommandPort ); } @@ -71,6 +82,17 @@ void successJoin() { given(roomCommandPort.findById(ROOM_ID)).willReturn(Optional.of(room)); given(roomParticipantCommandPort.findByUserIdAndRoomIdOptional(USER_ID, ROOM_ID)) .willReturn(Optional.empty()); + given(roomParticipantCommandPort.findHostByRoomId(any())) + .willReturn(RoomParticipant.hostWithoutId(100L, ROOM_ID)); + given(roomParticipantCommandPort.findAllByRoomId(any())).willReturn( + List.of( + RoomParticipant.memberWithoutId(3L, ROOM_ID), + RoomParticipant.memberWithoutId(4L, ROOM_ID) + ) + ); + given(userCommandPort.findById(any())).willReturn( + User.withoutId("nickname", "์ผ๋ฐ˜์œ ์ €", "kakao_1234", Alias.WRITER) + ); roomJoinService.changeJoinState(command); diff --git a/src/test/java/konkuk/thip/user/application/service/UserFollowServiceTest.java b/src/test/java/konkuk/thip/user/application/service/UserFollowServiceTest.java index f749f1d5d..84471a5d9 100644 --- a/src/test/java/konkuk/thip/user/application/service/UserFollowServiceTest.java +++ b/src/test/java/konkuk/thip/user/application/service/UserFollowServiceTest.java @@ -1,6 +1,7 @@ package konkuk.thip.user.application.service; import konkuk.thip.common.exception.BusinessException; +import konkuk.thip.message.application.port.out.FeedEventCommandPort; import konkuk.thip.user.application.port.in.dto.UserFollowCommand; import konkuk.thip.user.application.port.out.FollowingCommandPort; import konkuk.thip.user.application.port.out.UserCommandPort; @@ -28,11 +29,14 @@ class UserFollowServiceTest { private UserCommandPort userCommandPort; private UserFollowService userFollowService; + private FeedEventCommandPort feedEventCommandPort; + @BeforeEach void setUp() { followingCommandPort = mock(FollowingCommandPort.class); userCommandPort = mock(UserCommandPort.class); - userFollowService = new UserFollowService(followingCommandPort, userCommandPort); + feedEventCommandPort = mock(FeedEventCommandPort.class); + userFollowService = new UserFollowService(followingCommandPort, userCommandPort, feedEventCommandPort); } @Nested @@ -68,6 +72,7 @@ void follow_newRelation() { User user = createUserWithFollowerCount(0); when(userCommandPort.findById(targetUserId)).thenReturn(user); + when(userCommandPort.findById(userId)).thenReturn(user); // ์•Œ๋ฆผ ์ „์†ก์šฉ UserFollowCommand command = new UserFollowCommand(userId, targetUserId, true); From 632523f0a9ac559d4ae56081cd676412ccfafb45 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 02:47:01 +0900 Subject: [PATCH 50/93] =?UTF-8?q?[fix]=20=EC=B0=B8=EC=97=AC=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20=EC=8B=9C=EC=97=90=EB=A7=8C=20=EC=95=8C=EB=9E=8C=20?= =?UTF-8?q?=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EB=B0=9C=ED=96=89=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../konkuk/thip/room/application/service/RoomJoinService.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/konkuk/thip/room/application/service/RoomJoinService.java b/src/main/java/konkuk/thip/room/application/service/RoomJoinService.java index ca11ca1dd..3f4167821 100644 --- a/src/main/java/konkuk/thip/room/application/service/RoomJoinService.java +++ b/src/main/java/konkuk/thip/room/application/service/RoomJoinService.java @@ -52,7 +52,9 @@ public RoomJoinResult changeJoinState(RoomJoinCommand roomJoinCommand) { roomCommandPort.update(room); // ์ฐธ์—ฌ์ž ํ‘ธ์‰ฌ ์•Œ๋ฆผ ์ „์†ก (ํ˜ธ์ŠคํŠธ์—๊ฒŒ๋งŒ ์ „์†ก) - sendNotifications(roomJoinCommand, room); + if (type == RoomJoinType.JOIN) { + sendNotifications(roomJoinCommand, room); + } return RoomJoinResult.of(room.getId(), type.getType()); } From 906a41f37652a065fbecca9f1f9091aea64dde60 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 03:05:19 +0900 Subject: [PATCH 51/93] =?UTF-8?q?[test]=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=EB=84=88=20=EB=8B=A8=EC=9C=84=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../in/event/MessageFeedEventListener.java | 1 - .../event/MessageFeedEventListenerTest.java | 48 +++++++++++++++++++ .../event/MessageRoomEventListenerTest.java | 45 +++++++++++++++++ 3 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 src/test/java/konkuk/thip/message/adapter/in/event/MessageFeedEventListenerTest.java create mode 100644 src/test/java/konkuk/thip/message/adapter/in/event/MessageRoomEventListenerTest.java diff --git a/src/main/java/konkuk/thip/message/adapter/in/event/MessageFeedEventListener.java b/src/main/java/konkuk/thip/message/adapter/in/event/MessageFeedEventListener.java index 0046465e2..e8e97855e 100644 --- a/src/main/java/konkuk/thip/message/adapter/in/event/MessageFeedEventListener.java +++ b/src/main/java/konkuk/thip/message/adapter/in/event/MessageFeedEventListener.java @@ -1,4 +1,3 @@ -// notification/adapter/in/event/NotificationEventHandler.java (๋ฐœ์ทŒ: Room ๊ด€๋ จ ๋ฉ”์„œ๋“œ๋งŒ) package konkuk.thip.message.adapter.in.event; import konkuk.thip.message.adapter.out.event.dto.FeedEvents; diff --git a/src/test/java/konkuk/thip/message/adapter/in/event/MessageFeedEventListenerTest.java b/src/test/java/konkuk/thip/message/adapter/in/event/MessageFeedEventListenerTest.java new file mode 100644 index 000000000..bbd7ee37e --- /dev/null +++ b/src/test/java/konkuk/thip/message/adapter/in/event/MessageFeedEventListenerTest.java @@ -0,0 +1,48 @@ +// src/test/java/konkuk/thip/message/adapter/in/event/MessageFeedEventListenerTest.java +package konkuk.thip.message.adapter.in.event; + +import konkuk.thip.message.adapter.out.event.dto.FeedEvents; +import konkuk.thip.message.application.port.in.FeedNotificationDispatchUseCase; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.transaction.TestTransaction; +import org.springframework.transaction.annotation.Transactional; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +@SpringBootTest +@ActiveProfiles("test") +@DisplayName("[๋‹จ์œ„] MessageRoomEventListener ๋‹จ์œ„ ํ…Œ์ŠคํŠธ") +class MessageFeedEventListenerTest { + + @Autowired + private org.springframework.context.ApplicationEventPublisher publisher; + + @MockitoBean + private FeedNotificationDispatchUseCase feedUseCase; + + @Test + @Transactional + @DisplayName("FollowerEvent ๋ฐœํ–‰ โ†’ ์ปค๋ฐ‹ ์‹œ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๊ฐ€ useCase.handleFollower ํ˜ธ์ถœ") + void follower_isHandled_afterCommit() { + // given + var e = FeedEvents.FollowerEvent.builder() + .targetUserId(1L).actorUserId(2L).actorUsername("bob").build(); + + // when: ํŠธ๋žœ์žญ์…˜ ์•ˆ์—์„œ ์ด๋ฒคํŠธ ๋ฐœํ–‰ + publisher.publishEvent(e); + + // THEN: AFTER_COMMIT ์‹œ์  ๋งŒ๋“ค์–ด์ฃผ๊ธฐ + TestTransaction.flagForCommit(); + TestTransaction.end(); // ์—ฌ๊ธฐ์„œ @TransactionalEventListener(AFTER_COMMIT) ์‹คํ–‰ + + // then + verify(feedUseCase, times(1)).handleFollower(Mockito.eq(e)); + } +} \ No newline at end of file diff --git a/src/test/java/konkuk/thip/message/adapter/in/event/MessageRoomEventListenerTest.java b/src/test/java/konkuk/thip/message/adapter/in/event/MessageRoomEventListenerTest.java new file mode 100644 index 000000000..25d89a434 --- /dev/null +++ b/src/test/java/konkuk/thip/message/adapter/in/event/MessageRoomEventListenerTest.java @@ -0,0 +1,45 @@ +package konkuk.thip.message.adapter.in.event; + +import konkuk.thip.message.adapter.out.event.dto.RoomEvents; +import konkuk.thip.message.application.port.in.RoomNotificationDispatchUseCase; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.context.transaction.TestTransaction; +import org.springframework.transaction.annotation.Transactional; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +@SpringBootTest +@ActiveProfiles("test") +@DisplayName("[๋‹จ์œ„] MessageRoomEventListener ๋‹จ์œ„ ํ…Œ์ŠคํŠธ") +class MessageRoomEventListenerTest { + + @Autowired + private org.springframework.context.ApplicationEventPublisher publisher; + + @MockitoBean + private RoomNotificationDispatchUseCase roomUseCase; + + @Test + @Transactional + @DisplayName("RoomPostCommentedEvent ๋ฐœํ–‰ โ†’ ์ปค๋ฐ‹ ์‹œ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๊ฐ€ useCase.handleRoomPostCommented ํ˜ธ์ถœ") + void roomPostCommented_isHandled_afterCommit() { + var e = RoomEvents.RoomPostCommentedEvent.builder() + .targetUserId(10L).actorUserId(20L).actorUsername("alice") + .roomId(100L).page(12).postId(999L).postType("RECORD") + .build(); + + publisher.publishEvent(e); + + TestTransaction.flagForCommit(); + TestTransaction.end(); + + verify(roomUseCase, times(1)).handleRoomPostCommented(Mockito.eq(e)); + } +} \ No newline at end of file From 38f0d6509ba2fc2a222a238fbddb4d08227ee5b3 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 03:27:17 +0900 Subject: [PATCH 52/93] =?UTF-8?q?[chore]=20Firebase=20key=20=EC=A3=BC?= =?UTF-8?q?=EC=9E=85=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci-workflow.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index 525ecbb7f..11fc460d3 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -14,6 +14,7 @@ permissions: env: RESOURCE_PATH: src/main/resources TEST_RESOURCE_PATH: src/test/resources + FIREBASE_KEY_PATH: src/main/resources/firebase jobs: build: @@ -36,6 +37,12 @@ jobs: echo "${{ secrets.APPLICATION_YML_DEV }}" | base64 --decode > ${{ env.RESOURCE_PATH }}/application.yml echo "${{ secrets.APPLICATION_YML_TEST }}" | base64 --decode > ${{ env.TEST_RESOURCE_PATH }}/application-test.yml + - name: ๐Ÿ” Create Firebase Key from secret (base64) + run: | + mkdir -p ${{ env.FIREBASE_KEY_PATH }} + echo "${{ secrets.FIREBASE_KEY }}" | base64 --decode > ${{ env.FIREBASE_KEY_PATH }}/serviceAccountKey.json + shell: bash + - name: ๐Ÿ‘๐Ÿป grant execute permission for gradlew run: chmod +x gradlew From ead7faa5b267c113bf8f07ca32ba6861bafafe4c Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 12:52:53 +0900 Subject: [PATCH 53/93] =?UTF-8?q?[fix]=20=EC=9E=98=EB=AA=BB=EB=90=9C=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/application/service/CommentCreateService.java | 2 +- .../message/adapter/out/event/RoomEventPublisherAdapter.java | 2 +- .../message/application/port/out/RoomEventCommandPort.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/konkuk/thip/comment/application/service/CommentCreateService.java b/src/main/java/konkuk/thip/comment/application/service/CommentCreateService.java index a905c2758..25d8ab18e 100644 --- a/src/main/java/konkuk/thip/comment/application/service/CommentCreateService.java +++ b/src/main/java/konkuk/thip/comment/application/service/CommentCreateService.java @@ -99,7 +99,7 @@ private void sendNotifications(CommentCreateCommand command, PostType type, Coun roomEventCommandPort.publishRoomPostCommentedEvent(postQueryDto.creatorId(), actorUser.getId(), actorUser.getNickname(), postQueryDto.roomId(), postQueryDto.page(), postQueryDto.postId(), postQueryDto.postType()); if (command.isReplyRequest()){ // ๋ชจ์ž„๋ฐฉ ๊ฒŒ์‹œ๊ธ€ ๋‹ต๊ธ€ ์•Œ๋ฆผ ์ด๋ฒคํŠธ ๋ฐœํ–‰ - roomEventCommandPort.publicRoomPostCommentRepliedEvent(postQueryDto.creatorId(), actorUser.getId(), actorUser.getNickname(), postQueryDto.roomId(), postQueryDto.page(), postQueryDto.postId(), postQueryDto.postType()); + roomEventCommandPort.publishRoomPostCommentRepliedEvent(postQueryDto.creatorId(), actorUser.getId(), actorUser.getNickname(), postQueryDto.roomId(), postQueryDto.page(), postQueryDto.postId(), postQueryDto.postType()); } } } diff --git a/src/main/java/konkuk/thip/message/adapter/out/event/RoomEventPublisherAdapter.java b/src/main/java/konkuk/thip/message/adapter/out/event/RoomEventPublisherAdapter.java index 6cb1ef443..9d0e31380 100644 --- a/src/main/java/konkuk/thip/message/adapter/out/event/RoomEventPublisherAdapter.java +++ b/src/main/java/konkuk/thip/message/adapter/out/event/RoomEventPublisherAdapter.java @@ -110,7 +110,7 @@ public void publishRoomPostLikedEvent(Long targetUserId, Long actorUserId, Strin } @Override - public void publicRoomPostCommentRepliedEvent(Long targetUserId, Long actorUserId, String actorUsername, Long roomId, Integer page, Long postId, String postType) { + public void publishRoomPostCommentRepliedEvent(Long targetUserId, Long actorUserId, String actorUsername, Long roomId, Integer page, Long postId, String postType) { publisher.publishEvent(RoomEvents.RoomPostCommentRepliedEvent.builder() .targetUserId(targetUserId) .actorUserId(actorUserId) diff --git a/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java b/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java index 1c7dcd7a6..f4486321e 100644 --- a/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java +++ b/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java @@ -33,6 +33,6 @@ void publishRoomPostLikedEvent(Long targetUserId, Long actorUserId, String actor Long roomId, Integer page, Long postId, String postType); // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ์˜ ๋‚˜์˜ ๋Œ“๊ธ€์— ๋Œ€๋Œ“๊ธ€์ด ๋‹ฌ๋ฆฐ ๊ฒฝ์šฐ - void publicRoomPostCommentRepliedEvent(Long targetUserId, Long actorUserId, String actorUsername, - Long roomId, Integer page, Long postId, String postType); + void publishRoomPostCommentRepliedEvent(Long targetUserId, Long actorUserId, String actorUsername, + Long roomId, Integer page, Long postId, String postType); } \ No newline at end of file From 38c4783246f3dfb6f0e4ecdfab9c2d3f8a4f6fe9 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 13:18:22 +0900 Subject: [PATCH 54/93] =?UTF-8?q?[fix]=20feedId=20npe=20=ED=95=B4=EA=B2=B0?= =?UTF-8?q?=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feed/application/service/FeedCreateService.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/java/konkuk/thip/feed/application/service/FeedCreateService.java b/src/main/java/konkuk/thip/feed/application/service/FeedCreateService.java index ba109a388..a1aea4ac4 100644 --- a/src/main/java/konkuk/thip/feed/application/service/FeedCreateService.java +++ b/src/main/java/konkuk/thip/feed/application/service/FeedCreateService.java @@ -58,17 +58,20 @@ public Long createFeed(FeedCreateCommand command) { command.imageUrls() ); - // 4. ํ”ผ๋“œ ์ž‘์„ฑ ํ‘ธ์‰ฌ ์•Œ๋ฆผ ์ „์†ก - sendNotifications(command, feed); + // 4. ํ”ผ๋“œ ์˜์†ํ™” + Long savedFeedId = feedCommandPort.save(feed); - return feedCommandPort.save(feed); + // 5. ํ”ผ๋“œ ์ž‘์„ฑ ํ‘ธ์‰ฌ ์•Œ๋ฆผ ์ „์†ก + sendNotifications(command, savedFeedId); + + return savedFeedId; } - private void sendNotifications(FeedCreateCommand command, Feed feed) { + private void sendNotifications(FeedCreateCommand command, Long savedFeedId) { List targetUsers = userQueryPort.getAllFollowersByUserId(command.userId()); User actorUser = userCommandPort.findById(command.userId()); for (User targetUser : targetUsers) { - feedEventCommandPort.publishFolloweeNewPostEvent(targetUser.getId(), actorUser.getId(), actorUser.getNickname(), feed.getId()); + feedEventCommandPort.publishFolloweeNewPostEvent(targetUser.getId(), actorUser.getId(), actorUser.getNickname(), savedFeedId); } } From abd1019c9b9077f527a9a2edfce499b4da1847bb Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 13:18:39 +0900 Subject: [PATCH 55/93] =?UTF-8?q?[refactor]=20=EC=9E=90=EC=8B=A0=EC=9D=B4?= =?UTF-8?q?=20=EC=A2=8B=EC=95=84=EC=9A=94=20=EB=88=84=EB=A5=B8=EA=B2=BD?= =?UTF-8?q?=EC=9A=B0=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EB=B0=9C=ED=96=89=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/application/service/CommentLikeService.java | 8 +++++--- .../thip/post/application/service/PostLikeService.java | 3 +++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/konkuk/thip/comment/application/service/CommentLikeService.java b/src/main/java/konkuk/thip/comment/application/service/CommentLikeService.java index 9cf48a718..45899d8e2 100644 --- a/src/main/java/konkuk/thip/comment/application/service/CommentLikeService.java +++ b/src/main/java/konkuk/thip/comment/application/service/CommentLikeService.java @@ -54,7 +54,7 @@ public CommentIsLikeResult changeLikeStatusComment(CommentIsLikeCommand command) commentLikeCommandPort.save(command.userId(), command.commentId()); // ๋Œ“๊ธ€ ์ข‹์•„์š” ํ‘ธ์‰ฌ์•Œ๋ฆผ ์ „์†ก - sendNotifcations(command, comment); + sendNotifications(command, comment); } else { comment.validateCanUnlike(alreadyLiked); // ์ข‹์•„์š” ์ทจ์†Œ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ๊ฒ€์ฆ commentLikeCommandPort.delete(command.userId(), command.commentId()); @@ -67,11 +67,13 @@ public CommentIsLikeResult changeLikeStatusComment(CommentIsLikeCommand command) return CommentIsLikeResult.of(comment.getId(), command.isLike()); } - private void sendNotifcations(CommentIsLikeCommand command, Comment comment) { + private void sendNotifications(CommentIsLikeCommand command, Comment comment) { + if (command.userId().equals(comment.getCreatorId())) return; // ์ž์‹ ์˜ ๋Œ“๊ธ€์— ์ข‹์•„์š” ๋ˆ„๋ฅด๋Š” ๊ฒฝ์šฐ ์ œ์™ธ + User actorUser = userCommandPort.findById(command.userId()); // ์ข‹์•„์š” ํ‘ธ์‰ฌ์•Œ๋ฆผ ์ „์†ก if (comment.getPostType() == PostType.FEED) { - feedEventCommandPort.publishFeedCommentLikedEvent(comment.getCreatorId(), actorUser.getId(), actorUser.getNickname(), comment.getId()); + feedEventCommandPort.publishFeedCommentLikedEvent(comment.getCreatorId(), actorUser.getId(), actorUser.getNickname(), comment.getTargetPostId()); } if (comment.getPostType() == PostType.RECORD || comment.getPostType() == PostType.VOTE) { PostQueryDto postQueryDto = postHandler.getPostQueryDto(comment.getPostType(), comment.getTargetPostId()); diff --git a/src/main/java/konkuk/thip/post/application/service/PostLikeService.java b/src/main/java/konkuk/thip/post/application/service/PostLikeService.java index 09a179bf6..4ab27d818 100644 --- a/src/main/java/konkuk/thip/post/application/service/PostLikeService.java +++ b/src/main/java/konkuk/thip/post/application/service/PostLikeService.java @@ -68,6 +68,9 @@ public PostIsLikeResult changeLikeStatusPost(PostIsLikeCommand command) { private void sendNotifications(PostIsLikeCommand command) { PostQueryDto postQueryDto = postHandler.getPostQueryDto(command.postType(), command.postId()); + + if(command.userId().equals(postQueryDto.creatorId())) return; // ์ž์‹ ์˜ ๊ฒŒ์‹œ๊ธ€์— ์ข‹์•„์š” ๋ˆ„๋ฅด๋Š” ๊ฒฝ์šฐ ์ œ์™ธ + User actorUser = userCommandPort.findById(command.userId()); // ์ข‹์•„์š” ํ‘ธ์‰ฌ์•Œ๋ฆผ ์ „์†ก if (command.postType() == PostType.FEED) { From 267e1cc0811064afc1c212e767606047f29ed881 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 13:18:45 +0900 Subject: [PATCH 56/93] =?UTF-8?q?[refactor]=20=EC=97=90=EB=9F=AC=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=88=98=EC=A0=95=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/konkuk/thip/common/exception/code/ErrorCode.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java b/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java index 6832186ce..1db7c6607 100644 --- a/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java +++ b/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java @@ -215,8 +215,8 @@ public enum ErrorCode implements ResponseCode { * 200000 : Fcm error */ FCM_TOKEN_NOT_FOUND(HttpStatus.NOT_FOUND, 200000, "์กด์žฌํ•˜์ง€ ์•Š๋Š” FCM TOKEN ์ž…๋‹ˆ๋‹ค."), - FCM_TOKEN_ENABLED_STATE_ALREADY(HttpStatus.BAD_REQUEST, 200001, "์š”์ฒญํ•œ ์ƒํƒœ๋กœ ์ด๋ฏธ ํ‘ธ์‰ฌ์•Œ๋ฆผ ์—ฌ๋ถ€๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค."), - FIREBASE_SEND_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 200003, "FCM ํ‘ธ์‰ฌ์•Œ๋ฆผ ์ „์†ก์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.") + FCM_TOKEN_ENABLED_STATE_ALREADY(HttpStatus.BAD_REQUEST, 200001, "์š”์ฒญํ•œ ์ƒํƒœ๋กœ ์ด๋ฏธ ํ‘ธ์‰ฌ ์•Œ๋ฆผ ์—ฌ๋ถ€๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค."), + FIREBASE_SEND_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 200002, "FCM ํ‘ธ์‰ฌ ์•Œ๋ฆผ ์ „์†ก์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.") ; From 746e72a74e385aca4a5e7a27b72a4c275ef305da Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 13:26:10 +0900 Subject: [PATCH 57/93] =?UTF-8?q?[refactor]=20ThraedPool=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/BookCleanUpService.java | 2 +- .../java/konkuk/thip/config/AsyncConfig.java | 9 --- .../thip/config/WorkerThreadConfig.java | 62 +++++++++++++++++++ .../service/RoomStateChangeService.java | 3 +- 4 files changed, 65 insertions(+), 11 deletions(-) delete mode 100644 src/main/java/konkuk/thip/config/AsyncConfig.java create mode 100644 src/main/java/konkuk/thip/config/WorkerThreadConfig.java diff --git a/src/main/java/konkuk/thip/book/application/service/BookCleanUpService.java b/src/main/java/konkuk/thip/book/application/service/BookCleanUpService.java index e80b3999b..8e0f12a31 100644 --- a/src/main/java/konkuk/thip/book/application/service/BookCleanUpService.java +++ b/src/main/java/konkuk/thip/book/application/service/BookCleanUpService.java @@ -19,7 +19,7 @@ public class BookCleanUpService implements BookCleanUpUseCase { private final BookCommandPort bookCommandPort; private final BookQueryPort bookQueryPort; - @Async + @Async("schedulerAsyncExecutor") @Override @Transactional public void deleteUnusedBooks() { diff --git a/src/main/java/konkuk/thip/config/AsyncConfig.java b/src/main/java/konkuk/thip/config/AsyncConfig.java deleted file mode 100644 index 24247fa87..000000000 --- a/src/main/java/konkuk/thip/config/AsyncConfig.java +++ /dev/null @@ -1,9 +0,0 @@ -package konkuk.thip.config; - -import org.springframework.context.annotation.Configuration; -import org.springframework.scheduling.annotation.EnableAsync; - -@Configuration -@EnableAsync -public class AsyncConfig { -} diff --git a/src/main/java/konkuk/thip/config/WorkerThreadConfig.java b/src/main/java/konkuk/thip/config/WorkerThreadConfig.java new file mode 100644 index 000000000..88517f8f0 --- /dev/null +++ b/src/main/java/konkuk/thip/config/WorkerThreadConfig.java @@ -0,0 +1,62 @@ +package konkuk.thip.config; + +import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; +import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.AsyncConfigurer; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.Executor; + +@Configuration +@EnableAsync +public class WorkerThreadConfig implements AsyncConfigurer { + + /** + * FCM ํ‘ธ์‹œ์•Œ๋ฆผ ์ „์šฉ ์‹คํ–‰๊ธฐ + * - ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋“ค์˜ ์•Œ๋ฆผ ๋ฐœ์†ก ์ฒ˜๋ฆฌ + * - ๋นˆ๋ฒˆํ•œ ์งง์€ I/O ์ž‘์—… ์ตœ์ ํ™” + */ + @Bean(name = "fcmAsyncExecutor") + public Executor fcmAsyncExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(6); // FCM ์•Œ๋ฆผ ๊ธฐ๋ณธ ์ฒ˜๋ฆฌ๋Ÿ‰ + executor.setMaxPoolSize(15); // ์•Œ๋ฆผ ๊ธ‰์ฆ ์‹œ ํ™•์žฅ + executor.setQueueCapacity(100); // ์•Œ๋ฆผ ๋Œ€๊ธฐ ํ (์ ๋‹นํ•œ ํฌ๊ธฐ) + executor.setThreadNamePrefix("fcm-"); + executor.setWaitForTasksToCompleteOnShutdown(true); +// executor.setAwaitTerminationSeconds(30); + executor.initialize(); + return executor; + } + + /** + * ์Šค์ผ€์ค„๋Ÿฌ ๋ฐฐ์น˜์ž‘์—… ์ „์šฉ ์‹คํ–‰๊ธฐ + * - ๋ฐ์ดํ„ฐ ์ •๋ฆฌ, ๋ฐฉ ์ƒํƒœ ๋ณ€๊ฒฝ ๋“ฑ ๋ฐฐ์น˜ ์ž‘์—… + * - ๊ธด ์‹คํ–‰์‹œ๊ฐ„ ์ž‘์—… ์ตœ์ ํ™” + */ + @Bean(name = "schedulerAsyncExecutor") + public Executor schedulerAsyncExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(2); // ๋ฐฐ์น˜์ž‘์—…์€ ์ ์€ ๋™์‹œ ์‹คํ–‰ + executor.setMaxPoolSize(4); // ์ตœ๋Œ€ ํ™•์žฅ๋„ ์ œํ•œ์  + executor.setQueueCapacity(10); // ์ž‘์€ ํ (์Šค์ผ€์ค„๋ง๋œ ์ž‘์—…์ด๋ฏ€๋กœ) + executor.setThreadNamePrefix("scheduler-"); + executor.setWaitForTasksToCompleteOnShutdown(true); +// executor.setAwaitTerminationSeconds(120); // ๋ฐฐ์น˜์ž‘์—… ์™„๋ฃŒ ๋Œ€๊ธฐ์‹œ๊ฐ„ + executor.initialize(); + return executor; + } + + @Override + public Executor getAsyncExecutor() { + return fcmAsyncExecutor(); // ๊ธฐ๋ณธ์€ FCM ํ’€ ์‚ฌ์šฉ + } + + @Override + public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { + return new SimpleAsyncUncaughtExceptionHandler(); + } +} \ No newline at end of file diff --git a/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java b/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java index a046a674d..eaa316743 100644 --- a/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java +++ b/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java @@ -28,7 +28,7 @@ public class RoomStateChangeService implements RoomStateChangeUseCase { /** * end_date < ์˜ค๋Š˜ => EXPIRED */ - @Async + @Async("schedulerAsyncExecutor") @Override @Transactional public void changeRoomStateToExpired() { @@ -39,6 +39,7 @@ public void changeRoomStateToExpired() { /** * start_date <= ์˜ค๋Š˜ AND end_date >= ์˜ค๋Š˜ => IN_PROGRESS */ + @Async("schedulerAsyncExecutor") @Override @Transactional public void changeRoomStateToProgress() { From 5e7089161787a43fcb38db6b88fde0b1d47cc575 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 13:27:33 +0900 Subject: [PATCH 58/93] =?UTF-8?q?[refactor]=20InputStream=20=EB=A9=94?= =?UTF-8?q?=EB=AA=A8=EB=A6=AC=20=ED=95=B4=EC=A0=9C=EB=A5=BC=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20try-with-resources=20=ED=8C=A8=ED=84=B4=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/konkuk/thip/config/FirebaseConfig.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/konkuk/thip/config/FirebaseConfig.java b/src/main/java/konkuk/thip/config/FirebaseConfig.java index 473059f5d..82037dce7 100644 --- a/src/main/java/konkuk/thip/config/FirebaseConfig.java +++ b/src/main/java/konkuk/thip/config/FirebaseConfig.java @@ -11,6 +11,7 @@ import org.springframework.core.io.ClassPathResource; import java.io.IOException; +import java.io.InputStream; @Configuration public class FirebaseConfig { @@ -22,8 +23,11 @@ FirebaseMessaging firebaseMessaging(FirebaseApp firebaseApp) { @Bean FirebaseApp firebaseApp(@Value("${firebase.file-path}") String filePath) throws IOException { - GoogleCredentials googleCredentials = GoogleCredentials - .fromStream(new ClassPathResource(filePath).getInputStream()); + GoogleCredentials googleCredentials; + ClassPathResource resource = new ClassPathResource(filePath); + try (InputStream in = resource.getInputStream()) { + googleCredentials = GoogleCredentials.fromStream(in); + } FirebaseOptions firebaseOptions = FirebaseOptions.builder() .setCredentials(googleCredentials) @@ -32,7 +36,6 @@ FirebaseApp firebaseApp(@Value("${firebase.file-path}") String filePath) throws if (FirebaseApp.getApps().isEmpty()) { return FirebaseApp.initializeApp(firebaseOptions); } - return FirebaseApp.getInstance(); } From 0260ae9023bf785deb0090572ec8948d504748bf Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 13:30:02 +0900 Subject: [PATCH 59/93] =?UTF-8?q?[docs]=20=EC=8A=A4=EC=9B=A8=EA=B1=B0=20dt?= =?UTF-8?q?o=20=EC=8A=A4=ED=82=A4=EB=A7=88=20=EC=B6=94=EA=B0=80=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/in/web/request/FcmTokenDeleteRequest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenDeleteRequest.java b/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenDeleteRequest.java index 12caae20d..97c69e483 100644 --- a/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenDeleteRequest.java +++ b/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenDeleteRequest.java @@ -1,8 +1,11 @@ package konkuk.thip.notification.adapter.in.web.request; +import io.swagger.v3.oas.annotations.media.Schema; import konkuk.thip.notification.application.port.in.dto.FcmTokenDeleteCommand; +@Schema(description = "ํ‘ธ์‹œ ์•Œ๋ฆผ ์„ค์ • ์‚ญ์ œ ์š”์ฒญ DTO") public record FcmTokenDeleteRequest( + @Schema(description = "๋””๋ฐ”์ด์Šค ๊ณ ์œ  ID", example = "device12345") String deviceId ) { public FcmTokenDeleteCommand toCommand(Long userId) { From 6507e54edbb5ac3e63ae5c2cbd3bf03cd31a381f Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 13:31:55 +0900 Subject: [PATCH 60/93] =?UTF-8?q?[feat]=20=ED=86=A0=ED=81=B0=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20dto=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=EC=B6=94=EA=B0=80=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/in/web/NotificationCommandController.java | 4 ++-- .../adapter/in/web/request/FcmTokenDeleteRequest.java | 2 ++ .../in/web/request/FcmTokenEnableStateChangeRequest.java | 4 ++++ .../adapter/in/web/request/FcmTokenRegisterRequest.java | 5 +++++ 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java b/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java index b7e7c8481..012887092 100644 --- a/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java +++ b/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java @@ -43,7 +43,7 @@ public BaseResponse registerFcmToken( @ExceptionDescription(FCM_TOKEN_ENABLE_STATE_CHANGE) @PatchMapping("/notifications/enable-state") public BaseResponse updatePushNotificationSetting( - @RequestBody FcmTokenEnableStateChangeRequest request, + @RequestBody @Valid FcmTokenEnableStateChangeRequest request, @Parameter(hidden = true) @UserId Long userId ) { return BaseResponse.ok( @@ -53,7 +53,7 @@ public BaseResponse updatePushNotificationSet @DeleteMapping("/fcm-tokens") @Operation(summary = "FCM ํ† ํฐ ์‚ญ์ œ", description = "์‚ฌ์šฉ์ž์˜ FCM ํ† ํฐ์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.") public BaseResponse deleteFcmToken( - @RequestBody FcmTokenDeleteRequest request, + @RequestBody @Valid FcmTokenDeleteRequest request, @Parameter(hidden = true) @UserId Long userId ) { fcmDeleteUseCase.deleteToken(request.toCommand(userId)); diff --git a/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenDeleteRequest.java b/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenDeleteRequest.java index 97c69e483..a18419a16 100644 --- a/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenDeleteRequest.java +++ b/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenDeleteRequest.java @@ -1,10 +1,12 @@ package konkuk.thip.notification.adapter.in.web.request; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; import konkuk.thip.notification.application.port.in.dto.FcmTokenDeleteCommand; @Schema(description = "ํ‘ธ์‹œ ์•Œ๋ฆผ ์„ค์ • ์‚ญ์ œ ์š”์ฒญ DTO") public record FcmTokenDeleteRequest( + @NotBlank @Schema(description = "๋””๋ฐ”์ด์Šค ๊ณ ์œ  ID", example = "device12345") String deviceId ) { diff --git a/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenEnableStateChangeRequest.java b/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenEnableStateChangeRequest.java index 9f1031b3b..d6d77bcb8 100644 --- a/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenEnableStateChangeRequest.java +++ b/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenEnableStateChangeRequest.java @@ -1,13 +1,17 @@ package konkuk.thip.notification.adapter.in.web.request; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import konkuk.thip.notification.application.port.in.dto.FcmEnableStateChangeCommand; @Schema(description = "ํ‘ธ์‹œ ์•Œ๋ฆผ ์„ค์ • ๋ณ€๊ฒฝ ์š”์ฒญ DTO") public record FcmTokenEnableStateChangeRequest( + @NotNull @Schema(description = "ํ‘ธ์‹œ ์•Œ๋ฆผ ์ˆ˜์‹  ์—ฌ๋ถ€", example = "true") boolean enable, + @NotBlank @Schema(description = "๋””๋ฐ”์ด์Šค ๊ณ ์œ  ID", example = "device12345") String deviceId ) { diff --git a/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenRegisterRequest.java b/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenRegisterRequest.java index b9897d1df..31f090480 100644 --- a/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenRegisterRequest.java +++ b/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenRegisterRequest.java @@ -1,17 +1,22 @@ package konkuk.thip.notification.adapter.in.web.request; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import konkuk.thip.notification.adapter.out.jpa.PlatformType; import konkuk.thip.notification.application.port.in.dto.FcmTokenRegisterCommand; @Schema(description = "FCM ํ† ํฐ ๋“ฑ๋ก ์š”์ฒญ DTO") public record FcmTokenRegisterRequest( + @NotBlank @Schema(description = "๋””๋ฐ”์ด์Šค ๊ณ ์œ  ID", example = "device12345") String deviceId, + @NotBlank @Schema(description = "FCM ํ† ํฐ", example = "fcm_token_example_123456") String fcmToken, + @NotNull @Schema(description = "ํ”Œ๋žซํผ ํƒ€์ž… (ANDROID ๋˜๋Š” WEB)", example = "ANDROID") PlatformType platformType ) { From b544e93b6c9202eee842067c5365f63505e877ea Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 13:38:00 +0900 Subject: [PATCH 61/93] =?UTF-8?q?[refactor]=20=ED=91=B8=EC=89=AC=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=ED=97=88=EC=9A=A9=20=EC=8B=9C=20=EC=9E=90=EC=8B=A0?= =?UTF-8?q?=EC=9D=B4=20=EC=86=8C=EC=9C=A0=ED=95=9C=20=ED=86=A0=ED=81=B0?= =?UTF-8?q?=EC=9D=B4=20=EC=95=84=EB=8B=90=20=EA=B2=BD=EC=9A=B0=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=EC=B2=98=EB=A6=AC=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../konkuk/thip/common/exception/code/ErrorCode.java | 3 ++- .../application/service/FcmEnableStateChangeService.java | 2 +- .../java/konkuk/thip/notification/domain/FcmToken.java | 9 ++++++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java b/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java index 1db7c6607..d4f2b4b47 100644 --- a/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java +++ b/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java @@ -216,7 +216,8 @@ public enum ErrorCode implements ResponseCode { */ FCM_TOKEN_NOT_FOUND(HttpStatus.NOT_FOUND, 200000, "์กด์žฌํ•˜์ง€ ์•Š๋Š” FCM TOKEN ์ž…๋‹ˆ๋‹ค."), FCM_TOKEN_ENABLED_STATE_ALREADY(HttpStatus.BAD_REQUEST, 200001, "์š”์ฒญํ•œ ์ƒํƒœ๋กœ ์ด๋ฏธ ํ‘ธ์‰ฌ ์•Œ๋ฆผ ์—ฌ๋ถ€๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค."), - FIREBASE_SEND_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 200002, "FCM ํ‘ธ์‰ฌ ์•Œ๋ฆผ ์ „์†ก์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.") + FCM_TOKEN_CHANGE_ENABLE_STATE_FORBIDDEN(HttpStatus.FORBIDDEN, 200002, "ํ† ํฐ์„ ์†Œ์œ ํ•˜๊ณ  ์žˆ๋Š” ๊ณ„์ •์ด ์•„๋‹™๋‹ˆ๋‹ค."), + FIREBASE_SEND_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 200003, "FCM ํ‘ธ์‰ฌ ์•Œ๋ฆผ ์ „์†ก์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.") ; diff --git a/src/main/java/konkuk/thip/notification/application/service/FcmEnableStateChangeService.java b/src/main/java/konkuk/thip/notification/application/service/FcmEnableStateChangeService.java index a300073db..36c52a82e 100644 --- a/src/main/java/konkuk/thip/notification/application/service/FcmEnableStateChangeService.java +++ b/src/main/java/konkuk/thip/notification/application/service/FcmEnableStateChangeService.java @@ -19,7 +19,7 @@ public class FcmEnableStateChangeService implements FcmEnableStateChangeUseCase public boolean changeEnableState(FcmEnableStateChangeCommand command) { FcmToken fcmToken = fcmTokenLoadPort.getByDeviceIdOrThrow(command.deviceId()); - fcmToken.changeEnableState(command.enable()); + fcmToken.changeEnableState(command.enable(), command.userId()); fcmTokenLoadPort.update(fcmToken); return command.enable(); diff --git a/src/main/java/konkuk/thip/notification/domain/FcmToken.java b/src/main/java/konkuk/thip/notification/domain/FcmToken.java index a7e1b91e6..75a9ba74e 100644 --- a/src/main/java/konkuk/thip/notification/domain/FcmToken.java +++ b/src/main/java/konkuk/thip/notification/domain/FcmToken.java @@ -53,15 +53,18 @@ public void updateToken(String fcmToken, PlatformType platformType, LocalDate la this.userId = userId; } - public void changeEnableState(boolean enable) { - validateChangeEnableState(enable); + public void changeEnableState(boolean enable, long actorUserId) { + validateChangeEnableState(enable, actorUserId); this.isEnabled = enable; } - private void validateChangeEnableState(boolean enable) { + private void validateChangeEnableState(boolean enable, long actorUserId) { if (this.isEnabled == enable) { throw new InvalidStateException(ErrorCode.FCM_TOKEN_ENABLED_STATE_ALREADY, new IllegalArgumentException("์ด๋ฏธ " + (enable ? "ํ™œ์„ฑํ™”" : "๋น„ํ™œ์„ฑํ™”") + "๋œ ์ƒํƒœ์ž…๋‹ˆ๋‹ค.")); } + if (this.userId != actorUserId) { + throw new InvalidStateException(ErrorCode.FCM_TOKEN_CHANGE_ENABLE_STATE_FORBIDDEN); + } } } From 5409f0280345d9aae7a7602249260a4b0c46ca6f Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 13:45:22 +0900 Subject: [PATCH 62/93] =?UTF-8?q?[fix]=20=EC=B1=85=20=EC=83=81=ED=83=9C=20?= =?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EC=BF=BC=EB=A6=AC=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../out/persistence/RoomCommandPersistenceAdapter.java | 4 ++-- .../out/persistence/repository/RoomJpaRepository.java | 10 +++++----- .../room/application/port/out/RoomCommandPort.java | 2 +- .../application/service/RoomStateChangeService.java | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomCommandPersistenceAdapter.java b/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomCommandPersistenceAdapter.java index c9486a9b2..50a553059 100644 --- a/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomCommandPersistenceAdapter.java +++ b/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomCommandPersistenceAdapter.java @@ -65,8 +65,8 @@ public int updateRoomStateToExpired(RoomStatus exceptStatus) { } @Override - public int updateRoomStateToInProgress(RoomStatus roomStatus) { - return roomJpaRepository.updateRoomStatusToInProgress(roomStatus); + public int updateRoomStateToInProgress(RoomStatus fromStatus, RoomStatus toStatus) { + return roomJpaRepository.updateRoomStatusToInProgress(fromStatus, toStatus); } @Override diff --git a/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/RoomJpaRepository.java b/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/RoomJpaRepository.java index 448e32eaf..75990f159 100644 --- a/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/RoomJpaRepository.java +++ b/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/RoomJpaRepository.java @@ -34,7 +34,7 @@ public interface RoomJpaRepository extends JpaRepository, R where r.endDate < current_date and r.roomStatus <> :exceptStatus """) - int updateRoomStatusToExpired(RoomStatus exceptStatus); + int updateRoomStatusToExpired(@Param("exceptStatus") RoomStatus exceptStatus); /** * start_date <= ์˜ค๋Š˜ AND end_date >= ์˜ค๋Š˜ => IN_PROGRESS @@ -43,12 +43,12 @@ public interface RoomJpaRepository extends JpaRepository, R @Modifying(clearAutomatically = true, flushAutomatically = true) @Query(""" update RoomJpaEntity r - set r.roomStatus = :status + set r.roomStatus = :toStatus where r.startDate <= current_date and r.endDate >= current_date - and r.roomStatus = :status + and r.roomStatus = :fromStatus """) - int updateRoomStatusToInProgress(RoomStatus status); + int updateRoomStatusToInProgress(@Param("fromStatus") RoomStatus fromStatus, @Param("toStatus") RoomStatus toStatus); @Query(""" select r @@ -57,5 +57,5 @@ public interface RoomJpaRepository extends JpaRepository, R and r.endDate >= current_date and r.roomStatus = :status """) - List findProgressTargetIds(RoomStatus status); + List findProgressTargetIds(@Param("status") RoomStatus status); } diff --git a/src/main/java/konkuk/thip/room/application/port/out/RoomCommandPort.java b/src/main/java/konkuk/thip/room/application/port/out/RoomCommandPort.java index e48a07664..3d73ed762 100644 --- a/src/main/java/konkuk/thip/room/application/port/out/RoomCommandPort.java +++ b/src/main/java/konkuk/thip/room/application/port/out/RoomCommandPort.java @@ -24,7 +24,7 @@ default Room getByIdOrThrow(Long id) { int updateRoomStateToExpired(RoomStatus exceptStatus); - int updateRoomStateToInProgress(RoomStatus roomStatus); + int updateRoomStateToInProgress(RoomStatus fromStatus, RoomStatus toStatus); List findProgressTargetRooms(RoomStatus status); } diff --git a/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java b/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java index eaa316743..e3edf511b 100644 --- a/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java +++ b/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java @@ -46,7 +46,7 @@ public void changeRoomStateToProgress() { // ๋ฐฉ ๋ชจ์ž„๋ฐฉ ํ™œ๋™ ์‹œ์ž‘ ํ‘ธ์‰ฌ์•Œ๋ฆผ ์ „์†ก sendNotifications(); - int updated = roomCommandPort.updateRoomStateToInProgress(RoomStatus.RECRUITING); + int updated = roomCommandPort.updateRoomStateToInProgress(RoomStatus.RECRUITING, RoomStatus.IN_PROGRESS); log.info("[RoomState] IN_PROGRESS๋กœ ๋ณ€๊ฒฝ๋œ ๊ฑด์ˆ˜={}", updated); } From fc9352c8f78bcb5779b2ff2fc8b205d27bf3d750 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 13:45:31 +0900 Subject: [PATCH 63/93] =?UTF-8?q?[refactor]=20Param=20=EB=B0=94=EC=9D=B8?= =?UTF-8?q?=EB=94=A9=20=EC=B6=94=EA=B0=80=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../roomparticipant/RoomParticipantJpaRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/roomparticipant/RoomParticipantJpaRepository.java b/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/roomparticipant/RoomParticipantJpaRepository.java index 1dfe434d3..553dca1b6 100644 --- a/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/roomparticipant/RoomParticipantJpaRepository.java +++ b/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/roomparticipant/RoomParticipantJpaRepository.java @@ -33,5 +33,5 @@ public interface RoomParticipantJpaRepository extends JpaRepository findHostByRoomId(Long roomId); + Optional findHostByRoomId(@Param("roomId") Long roomId); } From becb58b469bc471a6d28df2e6b67e125474cbb26 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 13:48:50 +0900 Subject: [PATCH 64/93] =?UTF-8?q?[rename]=20=EA=B0=92=20=EA=B0=9D=EC=B2=B4?= =?UTF-8?q?=20=EB=AA=A8=EB=91=90=20domain=20=ED=95=98=EC=9C=84=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=EB=A1=9C=20=EC=9D=B4=EB=8F=99=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/book/application/service/BookSearchService.java | 2 +- .../adapter/in/web/request/FcmTokenRegisterRequest.java | 2 +- .../thip/notification/adapter/out/jpa/FcmTokenJpaEntity.java | 1 + .../thip/notification/adapter/out/jpa/PlatformType.java | 5 ----- .../application/port/in/dto/FcmTokenRegisterCommand.java | 2 +- src/main/java/konkuk/thip/notification/domain/FcmToken.java | 2 +- .../konkuk/thip/notification/domain/value/PlatformType.java | 5 +++++ .../recentSearch/adapter/out/jpa/RecentSearchJpaEntity.java | 1 + .../out/persistence/RecentSearchQueryPersistenceAdapter.java | 2 +- .../persistence/repository/RecentSearchQueryRepository.java | 2 +- .../repository/RecentSearchQueryRepositoryImpl.java | 2 +- .../application/port/out/RecentSearchQueryPort.java | 2 +- .../application/service/RecentSearchGetService.java | 2 +- .../service/manager/RecentSearchCreateManager.java | 2 +- .../java/konkuk/thip/recentSearch/domain/RecentSearch.java | 2 +- .../{adapter/out/jpa => domain/value}/RecentSearchType.java | 2 +- .../java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntity.java | 1 + .../thip/room/adapter/out/jpa/RoomParticipantJpaEntity.java | 1 + .../thip/room/adapter/out/mapper/RoomParticipantMapper.java | 2 +- .../out/persistence/RoomCommandPersistenceAdapter.java | 2 +- .../out/persistence/repository/RoomJpaRepository.java | 2 +- .../thip/room/application/port/out/RoomCommandPort.java | 2 +- .../thip/room/application/service/RoomSearchService.java | 2 +- .../room/application/service/RoomStateChangeService.java | 2 +- src/main/java/konkuk/thip/room/domain/Room.java | 2 +- src/main/java/konkuk/thip/room/domain/RoomParticipant.java | 2 +- src/main/java/konkuk/thip/room/domain/RoomParticipants.java | 2 +- .../out/jpa => domain/value}/RoomParticipantRole.java | 2 +- .../room/{adapter/out/jpa => domain/value}/RoomStatus.java | 2 +- .../java/konkuk/thip/user/adapter/out/jpa/UserJpaEntity.java | 1 + .../java/konkuk/thip/user/adapter/out/mapper/UserMapper.java | 2 +- .../thip/user/application/service/UserSearchService.java | 2 +- .../thip/user/application/service/UserSignupService.java | 2 +- .../user/{adapter/out/jpa => domain/value}/UserRole.java | 2 +- .../thip/book/adapter/in/web/BookChangeSavedApiTest.java | 2 +- .../thip/book/adapter/in/web/BookDetailSearchApiTest.java | 4 ++-- .../book/adapter/in/web/BookGetSelectableListApiTest.java | 2 +- .../book/adapter/in/web/BookMostSearchedBooksApiTest.java | 2 +- .../thip/book/adapter/in/web/BookRecruitingRoomApiTest.java | 2 +- .../konkuk/thip/book/adapter/in/web/BookSearchApiTest.java | 4 ++-- .../thip/comment/adapter/in/web/CommentCreateApiTest.java | 2 +- .../comment/adapter/in/web/CommentCreateControllerTest.java | 2 +- .../thip/comment/adapter/in/web/CommentDeleteApiTest.java | 2 +- src/test/java/konkuk/thip/common/util/TestEntityFactory.java | 4 ++-- .../thip/feed/adapter/in/web/FeedRelatedWithBookApiTest.java | 2 +- .../adapter/in/web/RecentSearchDeleteApiTest.java | 2 +- .../recentSearch/adapter/in/web/RecentSearchGetApiTest.java | 2 +- .../thip/room/adapter/in/web/RoomCloseJoinApiTest.java | 4 ++-- .../konkuk/thip/room/adapter/in/web/RoomCreateApiTest.java | 2 +- .../room/adapter/in/web/RoomGetDeadlinePopularApiTest.java | 2 +- .../room/adapter/in/web/RoomGetHomeJoinedRoomsApiTest.java | 2 +- .../thip/room/adapter/in/web/RoomGetMemberListApiTest.java | 4 ++-- .../konkuk/thip/room/adapter/in/web/RoomJoinApiTest.java | 4 ++-- .../room/adapter/in/web/RoomParticipantDeleteApiTest.java | 4 ++-- .../room/adapter/in/web/RoomPlayingDetailViewApiTest.java | 4 ++-- .../room/adapter/in/web/RoomPostChangeLikeStatusApiTest.java | 2 +- .../in/web/RoomPostChangeLikeStatusControllerTest.java | 2 +- .../room/adapter/in/web/RoomRecruitingDetailViewApiTest.java | 3 ++- .../konkuk/thip/room/adapter/in/web/RoomShowMineApiTest.java | 3 +-- .../java/konkuk/thip/room/domain/RoomParticipantsTest.java | 2 +- .../adapter/in/web/AttendanceCheckCreateApiTest.java | 2 +- .../adapter/in/web/AttendanceCheckDeleteApiTest.java | 2 +- .../roompost/adapter/in/web/AttendanceCheckShowApiTest.java | 2 +- .../roompost/adapter/in/web/RecordCreateControllerTest.java | 2 +- .../thip/roompost/adapter/in/web/RecordDeleteApiTest.java | 2 +- .../thip/roompost/adapter/in/web/RecordPinApiTest.java | 2 +- .../thip/roompost/adapter/in/web/RecordUpdateApiTest.java | 2 +- .../thip/roompost/adapter/in/web/RoomPostSearchApiTest.java | 4 ++-- .../konkuk/thip/roompost/adapter/in/web/VoteApiTest.java | 2 +- .../thip/roompost/adapter/in/web/VoteCreateApiTest.java | 2 +- .../thip/roompost/adapter/in/web/VoteDeleteApiTest.java | 2 +- .../thip/roompost/adapter/in/web/VoteUpdateApiTest.java | 2 +- .../roompost/application/service/VoteCreateServiceTest.java | 2 +- .../konkuk/thip/user/adapter/in/web/UserFollowApiTest.java | 2 +- .../konkuk/thip/user/adapter/in/web/UserReactionApiTest.java | 2 +- .../konkuk/thip/user/adapter/in/web/UserSearchApiTest.java | 2 +- .../konkuk/thip/user/adapter/in/web/UserUpdateApiTest.java | 2 +- .../adapter/in/web/UserVerifyNicknameControllerTest.java | 2 +- .../konkuk/thip/user/adapter/out/jpa/UserJpaEntityTest.java | 1 + 79 files changed, 92 insertions(+), 86 deletions(-) delete mode 100644 src/main/java/konkuk/thip/notification/adapter/out/jpa/PlatformType.java create mode 100644 src/main/java/konkuk/thip/notification/domain/value/PlatformType.java rename src/main/java/konkuk/thip/recentSearch/{adapter/out/jpa => domain/value}/RecentSearchType.java (93%) rename src/main/java/konkuk/thip/room/{adapter/out/jpa => domain/value}/RoomParticipantRole.java (94%) rename src/main/java/konkuk/thip/room/{adapter/out/jpa => domain/value}/RoomStatus.java (63%) rename src/main/java/konkuk/thip/user/{adapter/out/jpa => domain/value}/UserRole.java (93%) diff --git a/src/main/java/konkuk/thip/book/application/service/BookSearchService.java b/src/main/java/konkuk/thip/book/application/service/BookSearchService.java index 3858d06aa..3493e5d73 100644 --- a/src/main/java/konkuk/thip/book/application/service/BookSearchService.java +++ b/src/main/java/konkuk/thip/book/application/service/BookSearchService.java @@ -27,7 +27,7 @@ import static konkuk.thip.book.adapter.out.api.naver.NaverApiUtil.PAGE_SIZE; import static konkuk.thip.common.exception.code.ErrorCode.*; -import static konkuk.thip.recentSearch.adapter.out.jpa.RecentSearchType.BOOK_SEARCH; +import static konkuk.thip.recentSearch.domain.value.RecentSearchType.BOOK_SEARCH; @Service @RequiredArgsConstructor diff --git a/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenRegisterRequest.java b/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenRegisterRequest.java index 31f090480..69b516421 100644 --- a/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenRegisterRequest.java +++ b/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenRegisterRequest.java @@ -3,7 +3,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; -import konkuk.thip.notification.adapter.out.jpa.PlatformType; +import konkuk.thip.notification.domain.value.PlatformType; import konkuk.thip.notification.application.port.in.dto.FcmTokenRegisterCommand; @Schema(description = "FCM ํ† ํฐ ๋“ฑ๋ก ์š”์ฒญ DTO") diff --git a/src/main/java/konkuk/thip/notification/adapter/out/jpa/FcmTokenJpaEntity.java b/src/main/java/konkuk/thip/notification/adapter/out/jpa/FcmTokenJpaEntity.java index 15871db8e..ec2070d34 100644 --- a/src/main/java/konkuk/thip/notification/adapter/out/jpa/FcmTokenJpaEntity.java +++ b/src/main/java/konkuk/thip/notification/adapter/out/jpa/FcmTokenJpaEntity.java @@ -3,6 +3,7 @@ import jakarta.persistence.*; import konkuk.thip.common.entity.BaseJpaEntity; import konkuk.thip.notification.domain.FcmToken; +import konkuk.thip.notification.domain.value.PlatformType; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; import lombok.*; diff --git a/src/main/java/konkuk/thip/notification/adapter/out/jpa/PlatformType.java b/src/main/java/konkuk/thip/notification/adapter/out/jpa/PlatformType.java deleted file mode 100644 index 303d5d246..000000000 --- a/src/main/java/konkuk/thip/notification/adapter/out/jpa/PlatformType.java +++ /dev/null @@ -1,5 +0,0 @@ -package konkuk.thip.notification.adapter.out.jpa; - -public enum PlatformType { - ANDROID, WEB -} diff --git a/src/main/java/konkuk/thip/notification/application/port/in/dto/FcmTokenRegisterCommand.java b/src/main/java/konkuk/thip/notification/application/port/in/dto/FcmTokenRegisterCommand.java index bc0b3738e..d25e8be28 100644 --- a/src/main/java/konkuk/thip/notification/application/port/in/dto/FcmTokenRegisterCommand.java +++ b/src/main/java/konkuk/thip/notification/application/port/in/dto/FcmTokenRegisterCommand.java @@ -1,6 +1,6 @@ package konkuk.thip.notification.application.port.in.dto; -import konkuk.thip.notification.adapter.out.jpa.PlatformType; +import konkuk.thip.notification.domain.value.PlatformType; import lombok.Builder; @Builder diff --git a/src/main/java/konkuk/thip/notification/domain/FcmToken.java b/src/main/java/konkuk/thip/notification/domain/FcmToken.java index 75a9ba74e..44a43bf8b 100644 --- a/src/main/java/konkuk/thip/notification/domain/FcmToken.java +++ b/src/main/java/konkuk/thip/notification/domain/FcmToken.java @@ -3,7 +3,7 @@ import konkuk.thip.common.entity.BaseDomainEntity; import konkuk.thip.common.exception.InvalidStateException; import konkuk.thip.common.exception.code.ErrorCode; -import konkuk.thip.notification.adapter.out.jpa.PlatformType; +import konkuk.thip.notification.domain.value.PlatformType; import lombok.Getter; import lombok.experimental.SuperBuilder; diff --git a/src/main/java/konkuk/thip/notification/domain/value/PlatformType.java b/src/main/java/konkuk/thip/notification/domain/value/PlatformType.java new file mode 100644 index 000000000..5ae99334f --- /dev/null +++ b/src/main/java/konkuk/thip/notification/domain/value/PlatformType.java @@ -0,0 +1,5 @@ +package konkuk.thip.notification.domain.value; + +public enum PlatformType { + ANDROID, WEB +} diff --git a/src/main/java/konkuk/thip/recentSearch/adapter/out/jpa/RecentSearchJpaEntity.java b/src/main/java/konkuk/thip/recentSearch/adapter/out/jpa/RecentSearchJpaEntity.java index 4218bd247..8ac1aabe3 100644 --- a/src/main/java/konkuk/thip/recentSearch/adapter/out/jpa/RecentSearchJpaEntity.java +++ b/src/main/java/konkuk/thip/recentSearch/adapter/out/jpa/RecentSearchJpaEntity.java @@ -3,6 +3,7 @@ import jakarta.persistence.*; import konkuk.thip.common.entity.BaseJpaEntity; +import konkuk.thip.recentSearch.domain.value.RecentSearchType; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; import lombok.*; diff --git a/src/main/java/konkuk/thip/recentSearch/adapter/out/persistence/RecentSearchQueryPersistenceAdapter.java b/src/main/java/konkuk/thip/recentSearch/adapter/out/persistence/RecentSearchQueryPersistenceAdapter.java index 3f049e8ac..780dadb30 100644 --- a/src/main/java/konkuk/thip/recentSearch/adapter/out/persistence/RecentSearchQueryPersistenceAdapter.java +++ b/src/main/java/konkuk/thip/recentSearch/adapter/out/persistence/RecentSearchQueryPersistenceAdapter.java @@ -1,6 +1,6 @@ package konkuk.thip.recentSearch.adapter.out.persistence; -import konkuk.thip.recentSearch.adapter.out.jpa.RecentSearchType; +import konkuk.thip.recentSearch.domain.value.RecentSearchType; import konkuk.thip.recentSearch.adapter.out.mapper.RecentSearchMapper; import konkuk.thip.recentSearch.adapter.out.persistence.repository.RecentSearchJpaRepository; import konkuk.thip.recentSearch.application.port.out.RecentSearchQueryPort; diff --git a/src/main/java/konkuk/thip/recentSearch/adapter/out/persistence/repository/RecentSearchQueryRepository.java b/src/main/java/konkuk/thip/recentSearch/adapter/out/persistence/repository/RecentSearchQueryRepository.java index 309713668..29abb70e1 100644 --- a/src/main/java/konkuk/thip/recentSearch/adapter/out/persistence/repository/RecentSearchQueryRepository.java +++ b/src/main/java/konkuk/thip/recentSearch/adapter/out/persistence/repository/RecentSearchQueryRepository.java @@ -1,7 +1,7 @@ package konkuk.thip.recentSearch.adapter.out.persistence.repository; import konkuk.thip.recentSearch.adapter.out.jpa.RecentSearchJpaEntity; -import konkuk.thip.recentSearch.adapter.out.jpa.RecentSearchType; +import konkuk.thip.recentSearch.domain.value.RecentSearchType; import java.util.List; import java.util.Optional; diff --git a/src/main/java/konkuk/thip/recentSearch/adapter/out/persistence/repository/RecentSearchQueryRepositoryImpl.java b/src/main/java/konkuk/thip/recentSearch/adapter/out/persistence/repository/RecentSearchQueryRepositoryImpl.java index 7bd65aef4..5f5993118 100644 --- a/src/main/java/konkuk/thip/recentSearch/adapter/out/persistence/repository/RecentSearchQueryRepositoryImpl.java +++ b/src/main/java/konkuk/thip/recentSearch/adapter/out/persistence/repository/RecentSearchQueryRepositoryImpl.java @@ -2,7 +2,7 @@ import com.querydsl.jpa.impl.JPAQueryFactory; import konkuk.thip.recentSearch.adapter.out.jpa.RecentSearchJpaEntity; -import konkuk.thip.recentSearch.adapter.out.jpa.RecentSearchType; +import konkuk.thip.recentSearch.domain.value.RecentSearchType; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; diff --git a/src/main/java/konkuk/thip/recentSearch/application/port/out/RecentSearchQueryPort.java b/src/main/java/konkuk/thip/recentSearch/application/port/out/RecentSearchQueryPort.java index 04c09d662..4759f27ef 100644 --- a/src/main/java/konkuk/thip/recentSearch/application/port/out/RecentSearchQueryPort.java +++ b/src/main/java/konkuk/thip/recentSearch/application/port/out/RecentSearchQueryPort.java @@ -1,6 +1,6 @@ package konkuk.thip.recentSearch.application.port.out; -import konkuk.thip.recentSearch.adapter.out.jpa.RecentSearchType; +import konkuk.thip.recentSearch.domain.value.RecentSearchType; import konkuk.thip.recentSearch.domain.RecentSearch; import java.util.List; diff --git a/src/main/java/konkuk/thip/recentSearch/application/service/RecentSearchGetService.java b/src/main/java/konkuk/thip/recentSearch/application/service/RecentSearchGetService.java index 11e013211..d50c362cc 100644 --- a/src/main/java/konkuk/thip/recentSearch/application/service/RecentSearchGetService.java +++ b/src/main/java/konkuk/thip/recentSearch/application/service/RecentSearchGetService.java @@ -1,7 +1,7 @@ package konkuk.thip.recentSearch.application.service; import konkuk.thip.recentSearch.adapter.in.web.response.RecentSearchGetResponse; -import konkuk.thip.recentSearch.adapter.out.jpa.RecentSearchType; +import konkuk.thip.recentSearch.domain.value.RecentSearchType; import konkuk.thip.recentSearch.application.RecentSearchQueryMapper; import konkuk.thip.recentSearch.application.port.in.RecentSearchGetUseCase; import konkuk.thip.recentSearch.application.port.out.RecentSearchQueryPort; diff --git a/src/main/java/konkuk/thip/recentSearch/application/service/manager/RecentSearchCreateManager.java b/src/main/java/konkuk/thip/recentSearch/application/service/manager/RecentSearchCreateManager.java index 4de7be665..111e3db1a 100644 --- a/src/main/java/konkuk/thip/recentSearch/application/service/manager/RecentSearchCreateManager.java +++ b/src/main/java/konkuk/thip/recentSearch/application/service/manager/RecentSearchCreateManager.java @@ -1,7 +1,7 @@ package konkuk.thip.recentSearch.application.service.manager; import konkuk.thip.common.annotation.application.HelperService; -import konkuk.thip.recentSearch.adapter.out.jpa.RecentSearchType; +import konkuk.thip.recentSearch.domain.value.RecentSearchType; import konkuk.thip.recentSearch.application.port.out.RecentSearchCommandPort; import konkuk.thip.recentSearch.application.port.out.RecentSearchQueryPort; import konkuk.thip.recentSearch.domain.RecentSearch; diff --git a/src/main/java/konkuk/thip/recentSearch/domain/RecentSearch.java b/src/main/java/konkuk/thip/recentSearch/domain/RecentSearch.java index 35d9a8ffc..38307eaea 100644 --- a/src/main/java/konkuk/thip/recentSearch/domain/RecentSearch.java +++ b/src/main/java/konkuk/thip/recentSearch/domain/RecentSearch.java @@ -1,7 +1,7 @@ package konkuk.thip.recentSearch.domain; import konkuk.thip.common.entity.BaseDomainEntity; -import konkuk.thip.recentSearch.adapter.out.jpa.RecentSearchType; +import konkuk.thip.recentSearch.domain.value.RecentSearchType; import lombok.Getter; import lombok.experimental.SuperBuilder; diff --git a/src/main/java/konkuk/thip/recentSearch/adapter/out/jpa/RecentSearchType.java b/src/main/java/konkuk/thip/recentSearch/domain/value/RecentSearchType.java similarity index 93% rename from src/main/java/konkuk/thip/recentSearch/adapter/out/jpa/RecentSearchType.java rename to src/main/java/konkuk/thip/recentSearch/domain/value/RecentSearchType.java index 2a301c3ae..6f7340324 100644 --- a/src/main/java/konkuk/thip/recentSearch/adapter/out/jpa/RecentSearchType.java +++ b/src/main/java/konkuk/thip/recentSearch/domain/value/RecentSearchType.java @@ -1,4 +1,4 @@ -package konkuk.thip.recentSearch.adapter.out.jpa; +package konkuk.thip.recentSearch.domain.value; import konkuk.thip.common.exception.InvalidStateException; diff --git a/src/main/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntity.java b/src/main/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntity.java index 0d0666352..cf1ae333d 100644 --- a/src/main/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntity.java +++ b/src/main/java/konkuk/thip/room/adapter/out/jpa/RoomJpaEntity.java @@ -6,6 +6,7 @@ import konkuk.thip.common.entity.BaseJpaEntity; import konkuk.thip.room.domain.value.Category; import konkuk.thip.room.domain.Room; +import konkuk.thip.room.domain.value.RoomStatus; import lombok.*; import java.time.LocalDate; diff --git a/src/main/java/konkuk/thip/room/adapter/out/jpa/RoomParticipantJpaEntity.java b/src/main/java/konkuk/thip/room/adapter/out/jpa/RoomParticipantJpaEntity.java index 3c75571c7..e54611c2e 100644 --- a/src/main/java/konkuk/thip/room/adapter/out/jpa/RoomParticipantJpaEntity.java +++ b/src/main/java/konkuk/thip/room/adapter/out/jpa/RoomParticipantJpaEntity.java @@ -4,6 +4,7 @@ import jakarta.persistence.*; import konkuk.thip.common.entity.BaseJpaEntity; import konkuk.thip.room.domain.RoomParticipant; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; import lombok.*; import org.hibernate.annotations.SQLDelete; diff --git a/src/main/java/konkuk/thip/room/adapter/out/mapper/RoomParticipantMapper.java b/src/main/java/konkuk/thip/room/adapter/out/mapper/RoomParticipantMapper.java index bf70e7863..69a1a433a 100644 --- a/src/main/java/konkuk/thip/room/adapter/out/mapper/RoomParticipantMapper.java +++ b/src/main/java/konkuk/thip/room/adapter/out/mapper/RoomParticipantMapper.java @@ -1,7 +1,7 @@ package konkuk.thip.room.adapter.out.mapper; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; import konkuk.thip.room.adapter.out.jpa.RoomParticipantJpaEntity; import konkuk.thip.room.domain.RoomParticipant; diff --git a/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomCommandPersistenceAdapter.java b/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomCommandPersistenceAdapter.java index 50a553059..c1bac561f 100644 --- a/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomCommandPersistenceAdapter.java +++ b/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomCommandPersistenceAdapter.java @@ -4,7 +4,7 @@ import konkuk.thip.book.adapter.out.persistence.repository.BookJpaRepository; import konkuk.thip.common.exception.EntityNotFoundException; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomStatus; +import konkuk.thip.room.domain.value.RoomStatus; import konkuk.thip.room.adapter.out.mapper.RoomMapper; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.application.port.out.RoomCommandPort; diff --git a/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/RoomJpaRepository.java b/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/RoomJpaRepository.java index 75990f159..248e9273c 100644 --- a/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/RoomJpaRepository.java +++ b/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/RoomJpaRepository.java @@ -1,7 +1,7 @@ package konkuk.thip.room.adapter.out.persistence.repository; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomStatus; +import konkuk.thip.room.domain.value.RoomStatus; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; diff --git a/src/main/java/konkuk/thip/room/application/port/out/RoomCommandPort.java b/src/main/java/konkuk/thip/room/application/port/out/RoomCommandPort.java index 3d73ed762..e965c7b77 100644 --- a/src/main/java/konkuk/thip/room/application/port/out/RoomCommandPort.java +++ b/src/main/java/konkuk/thip/room/application/port/out/RoomCommandPort.java @@ -1,7 +1,7 @@ package konkuk.thip.room.application.port.out; import konkuk.thip.common.exception.EntityNotFoundException; -import konkuk.thip.room.adapter.out.jpa.RoomStatus; +import konkuk.thip.room.domain.value.RoomStatus; import konkuk.thip.room.domain.Room; import java.util.List; diff --git a/src/main/java/konkuk/thip/room/application/service/RoomSearchService.java b/src/main/java/konkuk/thip/room/application/service/RoomSearchService.java index e3a0d3091..849a38051 100644 --- a/src/main/java/konkuk/thip/room/application/service/RoomSearchService.java +++ b/src/main/java/konkuk/thip/room/application/service/RoomSearchService.java @@ -2,7 +2,7 @@ import konkuk.thip.common.util.Cursor; import konkuk.thip.common.util.CursorBasedList; -import konkuk.thip.recentSearch.adapter.out.jpa.RecentSearchType; +import konkuk.thip.recentSearch.domain.value.RecentSearchType; import konkuk.thip.recentSearch.application.service.manager.RecentSearchCreateManager; import konkuk.thip.room.adapter.in.web.response.RoomSearchResponse; import konkuk.thip.room.application.mapper.RoomQueryMapper; diff --git a/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java b/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java index e3edf511b..eca383d89 100644 --- a/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java +++ b/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java @@ -1,7 +1,7 @@ package konkuk.thip.room.application.service; import konkuk.thip.message.application.port.out.RoomEventCommandPort; -import konkuk.thip.room.adapter.out.jpa.RoomStatus; +import konkuk.thip.room.domain.value.RoomStatus; import konkuk.thip.room.application.port.in.RoomStateChangeUseCase; import konkuk.thip.room.application.port.out.RoomCommandPort; import konkuk.thip.room.application.port.out.RoomParticipantCommandPort; diff --git a/src/main/java/konkuk/thip/room/domain/Room.java b/src/main/java/konkuk/thip/room/domain/Room.java index 010198b5b..ad992f0cd 100644 --- a/src/main/java/konkuk/thip/room/domain/Room.java +++ b/src/main/java/konkuk/thip/room/domain/Room.java @@ -4,7 +4,7 @@ import konkuk.thip.common.exception.InvalidStateException; import konkuk.thip.common.entity.StatusType; import konkuk.thip.common.exception.code.ErrorCode; -import konkuk.thip.room.adapter.out.jpa.RoomStatus; +import konkuk.thip.room.domain.value.RoomStatus; import konkuk.thip.room.domain.value.Category; import lombok.Getter; import lombok.experimental.SuperBuilder; diff --git a/src/main/java/konkuk/thip/room/domain/RoomParticipant.java b/src/main/java/konkuk/thip/room/domain/RoomParticipant.java index ca9c3b081..f76bf3f7d 100644 --- a/src/main/java/konkuk/thip/room/domain/RoomParticipant.java +++ b/src/main/java/konkuk/thip/room/domain/RoomParticipant.java @@ -2,7 +2,7 @@ import konkuk.thip.common.entity.BaseDomainEntity; import konkuk.thip.common.exception.InvalidStateException; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import lombok.Getter; import lombok.experimental.SuperBuilder; diff --git a/src/main/java/konkuk/thip/room/domain/RoomParticipants.java b/src/main/java/konkuk/thip/room/domain/RoomParticipants.java index cf247162f..bf3f58ab9 100644 --- a/src/main/java/konkuk/thip/room/domain/RoomParticipants.java +++ b/src/main/java/konkuk/thip/room/domain/RoomParticipants.java @@ -1,7 +1,7 @@ package konkuk.thip.room.domain; import konkuk.thip.common.exception.InvalidStateException; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import lombok.Getter; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/konkuk/thip/room/adapter/out/jpa/RoomParticipantRole.java b/src/main/java/konkuk/thip/room/domain/value/RoomParticipantRole.java similarity index 94% rename from src/main/java/konkuk/thip/room/adapter/out/jpa/RoomParticipantRole.java rename to src/main/java/konkuk/thip/room/domain/value/RoomParticipantRole.java index 9c818af65..42590a01a 100644 --- a/src/main/java/konkuk/thip/room/adapter/out/jpa/RoomParticipantRole.java +++ b/src/main/java/konkuk/thip/room/domain/value/RoomParticipantRole.java @@ -1,5 +1,5 @@ -package konkuk.thip.room.adapter.out.jpa; +package konkuk.thip.room.domain.value; import konkuk.thip.common.exception.InvalidStateException; import konkuk.thip.common.exception.code.ErrorCode; diff --git a/src/main/java/konkuk/thip/room/adapter/out/jpa/RoomStatus.java b/src/main/java/konkuk/thip/room/domain/value/RoomStatus.java similarity index 63% rename from src/main/java/konkuk/thip/room/adapter/out/jpa/RoomStatus.java rename to src/main/java/konkuk/thip/room/domain/value/RoomStatus.java index b1952c30f..50fe90d32 100644 --- a/src/main/java/konkuk/thip/room/adapter/out/jpa/RoomStatus.java +++ b/src/main/java/konkuk/thip/room/domain/value/RoomStatus.java @@ -1,4 +1,4 @@ -package konkuk.thip.room.adapter.out.jpa; +package konkuk.thip.room.domain.value; public enum RoomStatus { RECRUITING, diff --git a/src/main/java/konkuk/thip/user/adapter/out/jpa/UserJpaEntity.java b/src/main/java/konkuk/thip/user/adapter/out/jpa/UserJpaEntity.java index 1acef21e1..62473e3c3 100644 --- a/src/main/java/konkuk/thip/user/adapter/out/jpa/UserJpaEntity.java +++ b/src/main/java/konkuk/thip/user/adapter/out/jpa/UserJpaEntity.java @@ -5,6 +5,7 @@ import konkuk.thip.common.entity.BaseJpaEntity; import konkuk.thip.user.domain.value.Alias; import konkuk.thip.user.domain.User; +import konkuk.thip.user.domain.value.UserRole; import lombok.*; import org.hibernate.annotations.SQLDelete; diff --git a/src/main/java/konkuk/thip/user/adapter/out/mapper/UserMapper.java b/src/main/java/konkuk/thip/user/adapter/out/mapper/UserMapper.java index 0eaeacf67..bb479a7b3 100644 --- a/src/main/java/konkuk/thip/user/adapter/out/mapper/UserMapper.java +++ b/src/main/java/konkuk/thip/user/adapter/out/mapper/UserMapper.java @@ -1,7 +1,7 @@ package konkuk.thip.user.adapter.out.mapper; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; -import konkuk.thip.user.adapter.out.jpa.UserRole; +import konkuk.thip.user.domain.value.UserRole; import konkuk.thip.user.domain.User; import org.springframework.stereotype.Component; diff --git a/src/main/java/konkuk/thip/user/application/service/UserSearchService.java b/src/main/java/konkuk/thip/user/application/service/UserSearchService.java index e9c9a6267..098f428b3 100644 --- a/src/main/java/konkuk/thip/user/application/service/UserSearchService.java +++ b/src/main/java/konkuk/thip/user/application/service/UserSearchService.java @@ -1,6 +1,6 @@ package konkuk.thip.user.application.service; -import konkuk.thip.recentSearch.adapter.out.jpa.RecentSearchType; +import konkuk.thip.recentSearch.domain.value.RecentSearchType; import konkuk.thip.recentSearch.application.service.manager.RecentSearchCreateManager; import konkuk.thip.user.adapter.in.web.response.UserSearchResponse; import konkuk.thip.user.application.mapper.UserQueryMapper; diff --git a/src/main/java/konkuk/thip/user/application/service/UserSignupService.java b/src/main/java/konkuk/thip/user/application/service/UserSignupService.java index 04eb3323b..716a8c297 100644 --- a/src/main/java/konkuk/thip/user/application/service/UserSignupService.java +++ b/src/main/java/konkuk/thip/user/application/service/UserSignupService.java @@ -14,7 +14,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import static konkuk.thip.user.adapter.out.jpa.UserRole.USER; +import static konkuk.thip.user.domain.value.UserRole.USER; @Service diff --git a/src/main/java/konkuk/thip/user/adapter/out/jpa/UserRole.java b/src/main/java/konkuk/thip/user/domain/value/UserRole.java similarity index 93% rename from src/main/java/konkuk/thip/user/adapter/out/jpa/UserRole.java rename to src/main/java/konkuk/thip/user/domain/value/UserRole.java index 7bf0dc750..964394bfa 100644 --- a/src/main/java/konkuk/thip/user/adapter/out/jpa/UserRole.java +++ b/src/main/java/konkuk/thip/user/domain/value/UserRole.java @@ -1,5 +1,5 @@ -package konkuk.thip.user.adapter.out.jpa; +package konkuk.thip.user.domain.value; import lombok.Getter; diff --git a/src/test/java/konkuk/thip/book/adapter/in/web/BookChangeSavedApiTest.java b/src/test/java/konkuk/thip/book/adapter/in/web/BookChangeSavedApiTest.java index 543e136d2..fe5aa6855 100644 --- a/src/test/java/konkuk/thip/book/adapter/in/web/BookChangeSavedApiTest.java +++ b/src/test/java/konkuk/thip/book/adapter/in/web/BookChangeSavedApiTest.java @@ -10,7 +10,7 @@ import konkuk.thip.book.adapter.out.jpa.SavedBookJpaEntity; import konkuk.thip.book.adapter.out.persistence.repository.SavedBookJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; -import konkuk.thip.user.adapter.out.jpa.UserRole; +import konkuk.thip.user.domain.value.UserRole; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import konkuk.thip.user.domain.value.Alias; import org.junit.jupiter.api.AfterEach; diff --git a/src/test/java/konkuk/thip/book/adapter/in/web/BookDetailSearchApiTest.java b/src/test/java/konkuk/thip/book/adapter/in/web/BookDetailSearchApiTest.java index f3d07d72b..0da7110b4 100644 --- a/src/test/java/konkuk/thip/book/adapter/in/web/BookDetailSearchApiTest.java +++ b/src/test/java/konkuk/thip/book/adapter/in/web/BookDetailSearchApiTest.java @@ -8,14 +8,14 @@ import konkuk.thip.feed.adapter.out.persistence.repository.FeedJpaRepository; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.adapter.out.jpa.RoomParticipantJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.book.adapter.out.jpa.SavedBookJpaEntity; import konkuk.thip.book.adapter.out.persistence.repository.SavedBookJpaRepository; import konkuk.thip.room.domain.value.Category; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; -import konkuk.thip.user.adapter.out.jpa.UserRole; +import konkuk.thip.user.domain.value.UserRole; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import konkuk.thip.user.domain.value.Alias; import org.junit.jupiter.api.AfterEach; diff --git a/src/test/java/konkuk/thip/book/adapter/in/web/BookGetSelectableListApiTest.java b/src/test/java/konkuk/thip/book/adapter/in/web/BookGetSelectableListApiTest.java index 928891ec7..030332ce1 100644 --- a/src/test/java/konkuk/thip/book/adapter/in/web/BookGetSelectableListApiTest.java +++ b/src/test/java/konkuk/thip/book/adapter/in/web/BookGetSelectableListApiTest.java @@ -7,7 +7,7 @@ import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.adapter.out.jpa.RoomParticipantJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.room.domain.value.Category; diff --git a/src/test/java/konkuk/thip/book/adapter/in/web/BookMostSearchedBooksApiTest.java b/src/test/java/konkuk/thip/book/adapter/in/web/BookMostSearchedBooksApiTest.java index 13e416567..a1cec3e9d 100644 --- a/src/test/java/konkuk/thip/book/adapter/in/web/BookMostSearchedBooksApiTest.java +++ b/src/test/java/konkuk/thip/book/adapter/in/web/BookMostSearchedBooksApiTest.java @@ -5,7 +5,7 @@ import konkuk.thip.book.application.port.in.dto.BookMostSearchResult; import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; -import konkuk.thip.user.adapter.out.jpa.UserRole; +import konkuk.thip.user.domain.value.UserRole; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import konkuk.thip.user.domain.value.Alias; import org.junit.jupiter.api.AfterEach; diff --git a/src/test/java/konkuk/thip/book/adapter/in/web/BookRecruitingRoomApiTest.java b/src/test/java/konkuk/thip/book/adapter/in/web/BookRecruitingRoomApiTest.java index adfbc9bd2..93e0f5145 100644 --- a/src/test/java/konkuk/thip/book/adapter/in/web/BookRecruitingRoomApiTest.java +++ b/src/test/java/konkuk/thip/book/adapter/in/web/BookRecruitingRoomApiTest.java @@ -9,7 +9,7 @@ import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.domain.value.Category; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; -import konkuk.thip.user.adapter.out.jpa.UserRole; +import konkuk.thip.user.domain.value.UserRole; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import konkuk.thip.user.domain.value.Alias; import org.junit.jupiter.api.DisplayName; diff --git a/src/test/java/konkuk/thip/book/adapter/in/web/BookSearchApiTest.java b/src/test/java/konkuk/thip/book/adapter/in/web/BookSearchApiTest.java index d13fd4130..a2f307559 100644 --- a/src/test/java/konkuk/thip/book/adapter/in/web/BookSearchApiTest.java +++ b/src/test/java/konkuk/thip/book/adapter/in/web/BookSearchApiTest.java @@ -4,10 +4,10 @@ import konkuk.thip.common.security.util.JwtUtil; import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.recentSearch.adapter.out.jpa.RecentSearchJpaEntity; -import konkuk.thip.recentSearch.adapter.out.jpa.RecentSearchType; +import konkuk.thip.recentSearch.domain.value.RecentSearchType; import konkuk.thip.recentSearch.adapter.out.persistence.repository.RecentSearchJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; -import konkuk.thip.user.adapter.out.jpa.UserRole; +import konkuk.thip.user.domain.value.UserRole; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import konkuk.thip.user.domain.value.Alias; import org.junit.jupiter.api.AfterEach; diff --git a/src/test/java/konkuk/thip/comment/adapter/in/web/CommentCreateApiTest.java b/src/test/java/konkuk/thip/comment/adapter/in/web/CommentCreateApiTest.java index 7d0d26958..379e1c787 100644 --- a/src/test/java/konkuk/thip/comment/adapter/in/web/CommentCreateApiTest.java +++ b/src/test/java/konkuk/thip/comment/adapter/in/web/CommentCreateApiTest.java @@ -8,7 +8,7 @@ import konkuk.thip.feed.adapter.out.jpa.FeedJpaEntity; import konkuk.thip.feed.adapter.out.persistence.repository.FeedJpaRepository; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.room.domain.value.Category; diff --git a/src/test/java/konkuk/thip/comment/adapter/in/web/CommentCreateControllerTest.java b/src/test/java/konkuk/thip/comment/adapter/in/web/CommentCreateControllerTest.java index 4c1640329..7f9346f20 100644 --- a/src/test/java/konkuk/thip/comment/adapter/in/web/CommentCreateControllerTest.java +++ b/src/test/java/konkuk/thip/comment/adapter/in/web/CommentCreateControllerTest.java @@ -11,7 +11,7 @@ import konkuk.thip.roompost.adapter.out.jpa.RecordJpaEntity; import konkuk.thip.roompost.adapter.out.persistence.repository.record.RecordJpaRepository; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; diff --git a/src/test/java/konkuk/thip/comment/adapter/in/web/CommentDeleteApiTest.java b/src/test/java/konkuk/thip/comment/adapter/in/web/CommentDeleteApiTest.java index b39a96877..e0bdbd54a 100644 --- a/src/test/java/konkuk/thip/comment/adapter/in/web/CommentDeleteApiTest.java +++ b/src/test/java/konkuk/thip/comment/adapter/in/web/CommentDeleteApiTest.java @@ -12,7 +12,7 @@ import konkuk.thip.roompost.adapter.out.jpa.RecordJpaEntity; import konkuk.thip.roompost.adapter.out.persistence.repository.record.RecordJpaRepository; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; diff --git a/src/test/java/konkuk/thip/common/util/TestEntityFactory.java b/src/test/java/konkuk/thip/common/util/TestEntityFactory.java index 697458718..3f5a765f5 100644 --- a/src/test/java/konkuk/thip/common/util/TestEntityFactory.java +++ b/src/test/java/konkuk/thip/common/util/TestEntityFactory.java @@ -14,12 +14,12 @@ import konkuk.thip.post.domain.PostType; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.adapter.out.jpa.RoomParticipantJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.domain.value.Category; import konkuk.thip.roompost.adapter.out.jpa.*; import konkuk.thip.user.adapter.out.jpa.FollowingJpaEntity; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; -import konkuk.thip.user.adapter.out.jpa.UserRole; +import konkuk.thip.user.domain.value.UserRole; import konkuk.thip.user.domain.value.Alias; import java.time.LocalDate; diff --git a/src/test/java/konkuk/thip/feed/adapter/in/web/FeedRelatedWithBookApiTest.java b/src/test/java/konkuk/thip/feed/adapter/in/web/FeedRelatedWithBookApiTest.java index 66095fe48..1c5ec79b0 100644 --- a/src/test/java/konkuk/thip/feed/adapter/in/web/FeedRelatedWithBookApiTest.java +++ b/src/test/java/konkuk/thip/feed/adapter/in/web/FeedRelatedWithBookApiTest.java @@ -12,7 +12,7 @@ import konkuk.thip.post.adapter.out.persistence.PostLikeJpaRepository; import konkuk.thip.room.domain.value.Category; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; -import konkuk.thip.user.adapter.out.jpa.UserRole; +import konkuk.thip.user.domain.value.UserRole; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import konkuk.thip.user.domain.value.Alias; import org.junit.jupiter.api.DisplayName; diff --git a/src/test/java/konkuk/thip/recentSearch/adapter/in/web/RecentSearchDeleteApiTest.java b/src/test/java/konkuk/thip/recentSearch/adapter/in/web/RecentSearchDeleteApiTest.java index 6331a31d4..f1a875e3b 100644 --- a/src/test/java/konkuk/thip/recentSearch/adapter/in/web/RecentSearchDeleteApiTest.java +++ b/src/test/java/konkuk/thip/recentSearch/adapter/in/web/RecentSearchDeleteApiTest.java @@ -3,7 +3,7 @@ import konkuk.thip.common.exception.code.ErrorCode; import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.recentSearch.adapter.out.jpa.RecentSearchJpaEntity; -import konkuk.thip.recentSearch.adapter.out.jpa.RecentSearchType; +import konkuk.thip.recentSearch.domain.value.RecentSearchType; import konkuk.thip.recentSearch.adapter.out.persistence.repository.RecentSearchJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; diff --git a/src/test/java/konkuk/thip/recentSearch/adapter/in/web/RecentSearchGetApiTest.java b/src/test/java/konkuk/thip/recentSearch/adapter/in/web/RecentSearchGetApiTest.java index 64b351594..31075637d 100644 --- a/src/test/java/konkuk/thip/recentSearch/adapter/in/web/RecentSearchGetApiTest.java +++ b/src/test/java/konkuk/thip/recentSearch/adapter/in/web/RecentSearchGetApiTest.java @@ -3,7 +3,7 @@ import jakarta.persistence.EntityManager; import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.recentSearch.adapter.out.jpa.RecentSearchJpaEntity; -import konkuk.thip.recentSearch.adapter.out.jpa.RecentSearchType; +import konkuk.thip.recentSearch.domain.value.RecentSearchType; import konkuk.thip.recentSearch.adapter.out.persistence.repository.RecentSearchJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; diff --git a/src/test/java/konkuk/thip/room/adapter/in/web/RoomCloseJoinApiTest.java b/src/test/java/konkuk/thip/room/adapter/in/web/RoomCloseJoinApiTest.java index c69cda6e9..2a399c451 100644 --- a/src/test/java/konkuk/thip/room/adapter/in/web/RoomCloseJoinApiTest.java +++ b/src/test/java/konkuk/thip/room/adapter/in/web/RoomCloseJoinApiTest.java @@ -5,12 +5,12 @@ import konkuk.thip.book.adapter.out.persistence.repository.BookJpaRepository; import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.room.domain.value.Category; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; -import konkuk.thip.user.adapter.out.jpa.UserRole; +import konkuk.thip.user.domain.value.UserRole; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import konkuk.thip.user.domain.value.Alias; import org.junit.jupiter.api.AfterEach; diff --git a/src/test/java/konkuk/thip/room/adapter/in/web/RoomCreateApiTest.java b/src/test/java/konkuk/thip/room/adapter/in/web/RoomCreateApiTest.java index f732cc077..829039b1b 100644 --- a/src/test/java/konkuk/thip/room/adapter/in/web/RoomCreateApiTest.java +++ b/src/test/java/konkuk/thip/room/adapter/in/web/RoomCreateApiTest.java @@ -11,7 +11,7 @@ import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.room.domain.value.Category; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; -import konkuk.thip.user.adapter.out.jpa.UserRole; +import konkuk.thip.user.domain.value.UserRole; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import konkuk.thip.user.domain.value.Alias; import org.junit.jupiter.api.AfterEach; diff --git a/src/test/java/konkuk/thip/room/adapter/in/web/RoomGetDeadlinePopularApiTest.java b/src/test/java/konkuk/thip/room/adapter/in/web/RoomGetDeadlinePopularApiTest.java index 124a674d9..c3e1e72ad 100644 --- a/src/test/java/konkuk/thip/room/adapter/in/web/RoomGetDeadlinePopularApiTest.java +++ b/src/test/java/konkuk/thip/room/adapter/in/web/RoomGetDeadlinePopularApiTest.java @@ -5,7 +5,7 @@ import konkuk.thip.common.util.DateUtil; import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.room.domain.value.Category; diff --git a/src/test/java/konkuk/thip/room/adapter/in/web/RoomGetHomeJoinedRoomsApiTest.java b/src/test/java/konkuk/thip/room/adapter/in/web/RoomGetHomeJoinedRoomsApiTest.java index 658146dfa..1e30aa466 100644 --- a/src/test/java/konkuk/thip/room/adapter/in/web/RoomGetHomeJoinedRoomsApiTest.java +++ b/src/test/java/konkuk/thip/room/adapter/in/web/RoomGetHomeJoinedRoomsApiTest.java @@ -5,7 +5,7 @@ import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.adapter.out.jpa.RoomParticipantJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.domain.value.Category; import konkuk.thip.user.adapter.out.jpa.*; diff --git a/src/test/java/konkuk/thip/room/adapter/in/web/RoomGetMemberListApiTest.java b/src/test/java/konkuk/thip/room/adapter/in/web/RoomGetMemberListApiTest.java index dd2ceb508..480bba84d 100644 --- a/src/test/java/konkuk/thip/room/adapter/in/web/RoomGetMemberListApiTest.java +++ b/src/test/java/konkuk/thip/room/adapter/in/web/RoomGetMemberListApiTest.java @@ -4,12 +4,12 @@ import konkuk.thip.book.adapter.out.persistence.repository.BookJpaRepository; import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.room.domain.value.Category; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; -import konkuk.thip.user.adapter.out.jpa.UserRole; +import konkuk.thip.user.domain.value.UserRole; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import konkuk.thip.user.adapter.out.persistence.repository.following.FollowingJpaRepository; import konkuk.thip.user.domain.value.Alias; diff --git a/src/test/java/konkuk/thip/room/adapter/in/web/RoomJoinApiTest.java b/src/test/java/konkuk/thip/room/adapter/in/web/RoomJoinApiTest.java index 8b9164db5..f8e187a2e 100644 --- a/src/test/java/konkuk/thip/room/adapter/in/web/RoomJoinApiTest.java +++ b/src/test/java/konkuk/thip/room/adapter/in/web/RoomJoinApiTest.java @@ -6,12 +6,12 @@ import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.adapter.out.jpa.RoomParticipantJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.room.domain.value.Category; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; -import konkuk.thip.user.adapter.out.jpa.UserRole; +import konkuk.thip.user.domain.value.UserRole; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import konkuk.thip.user.domain.value.Alias; import org.junit.jupiter.api.AfterEach; diff --git a/src/test/java/konkuk/thip/room/adapter/in/web/RoomParticipantDeleteApiTest.java b/src/test/java/konkuk/thip/room/adapter/in/web/RoomParticipantDeleteApiTest.java index 6210bb75c..c61fa931d 100644 --- a/src/test/java/konkuk/thip/room/adapter/in/web/RoomParticipantDeleteApiTest.java +++ b/src/test/java/konkuk/thip/room/adapter/in/web/RoomParticipantDeleteApiTest.java @@ -7,12 +7,12 @@ import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.adapter.out.jpa.RoomParticipantJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.room.domain.value.Category; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; -import konkuk.thip.user.adapter.out.jpa.UserRole; +import konkuk.thip.user.domain.value.UserRole; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import konkuk.thip.user.domain.value.Alias; import org.junit.jupiter.api.DisplayName; diff --git a/src/test/java/konkuk/thip/room/adapter/in/web/RoomPlayingDetailViewApiTest.java b/src/test/java/konkuk/thip/room/adapter/in/web/RoomPlayingDetailViewApiTest.java index 1a60e42b4..90f6e4a24 100644 --- a/src/test/java/konkuk/thip/room/adapter/in/web/RoomPlayingDetailViewApiTest.java +++ b/src/test/java/konkuk/thip/room/adapter/in/web/RoomPlayingDetailViewApiTest.java @@ -6,12 +6,12 @@ import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.adapter.out.jpa.RoomParticipantJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.room.domain.value.Category; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; -import konkuk.thip.user.adapter.out.jpa.UserRole; +import konkuk.thip.user.domain.value.UserRole; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import konkuk.thip.roompost.adapter.out.jpa.VoteItemJpaEntity; import konkuk.thip.roompost.adapter.out.jpa.VoteJpaEntity; diff --git a/src/test/java/konkuk/thip/room/adapter/in/web/RoomPostChangeLikeStatusApiTest.java b/src/test/java/konkuk/thip/room/adapter/in/web/RoomPostChangeLikeStatusApiTest.java index f41349c8e..ff57ca399 100644 --- a/src/test/java/konkuk/thip/room/adapter/in/web/RoomPostChangeLikeStatusApiTest.java +++ b/src/test/java/konkuk/thip/room/adapter/in/web/RoomPostChangeLikeStatusApiTest.java @@ -12,7 +12,7 @@ import konkuk.thip.roompost.adapter.out.persistence.repository.record.RecordJpaRepository; import konkuk.thip.room.adapter.in.web.request.RoomPostIsLikeRequest; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; diff --git a/src/test/java/konkuk/thip/room/adapter/in/web/RoomPostChangeLikeStatusControllerTest.java b/src/test/java/konkuk/thip/room/adapter/in/web/RoomPostChangeLikeStatusControllerTest.java index f0057b227..e8b21e592 100644 --- a/src/test/java/konkuk/thip/room/adapter/in/web/RoomPostChangeLikeStatusControllerTest.java +++ b/src/test/java/konkuk/thip/room/adapter/in/web/RoomPostChangeLikeStatusControllerTest.java @@ -8,7 +8,7 @@ import konkuk.thip.roompost.adapter.out.jpa.RecordJpaEntity; import konkuk.thip.roompost.adapter.out.persistence.repository.record.RecordJpaRepository; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; diff --git a/src/test/java/konkuk/thip/room/adapter/in/web/RoomRecruitingDetailViewApiTest.java b/src/test/java/konkuk/thip/room/adapter/in/web/RoomRecruitingDetailViewApiTest.java index cbad6f571..0e11daa9b 100644 --- a/src/test/java/konkuk/thip/room/adapter/in/web/RoomRecruitingDetailViewApiTest.java +++ b/src/test/java/konkuk/thip/room/adapter/in/web/RoomRecruitingDetailViewApiTest.java @@ -6,13 +6,14 @@ import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.adapter.out.jpa.RoomParticipantJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.domain.value.Category; import konkuk.thip.user.adapter.out.jpa.*; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.user.domain.value.Alias; +import konkuk.thip.user.domain.value.UserRole; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/konkuk/thip/room/adapter/in/web/RoomShowMineApiTest.java b/src/test/java/konkuk/thip/room/adapter/in/web/RoomShowMineApiTest.java index b9f2b6854..f378428c9 100644 --- a/src/test/java/konkuk/thip/room/adapter/in/web/RoomShowMineApiTest.java +++ b/src/test/java/konkuk/thip/room/adapter/in/web/RoomShowMineApiTest.java @@ -6,7 +6,7 @@ import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.adapter.out.jpa.RoomParticipantJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.room.domain.value.Category; @@ -24,7 +24,6 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; -import java.sql.Timestamp; import java.time.LocalDate; import static konkuk.thip.common.exception.code.ErrorCode.INVALID_MY_ROOM_TYPE; diff --git a/src/test/java/konkuk/thip/room/domain/RoomParticipantsTest.java b/src/test/java/konkuk/thip/room/domain/RoomParticipantsTest.java index a935d5a94..7c1361a34 100644 --- a/src/test/java/konkuk/thip/room/domain/RoomParticipantsTest.java +++ b/src/test/java/konkuk/thip/room/domain/RoomParticipantsTest.java @@ -1,7 +1,7 @@ package konkuk.thip.room.domain; import konkuk.thip.common.exception.InvalidStateException; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/konkuk/thip/roompost/adapter/in/web/AttendanceCheckCreateApiTest.java b/src/test/java/konkuk/thip/roompost/adapter/in/web/AttendanceCheckCreateApiTest.java index 99493b7fd..a3117747d 100644 --- a/src/test/java/konkuk/thip/roompost/adapter/in/web/AttendanceCheckCreateApiTest.java +++ b/src/test/java/konkuk/thip/roompost/adapter/in/web/AttendanceCheckCreateApiTest.java @@ -8,7 +8,7 @@ import konkuk.thip.book.adapter.out.persistence.repository.BookJpaRepository; import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; diff --git a/src/test/java/konkuk/thip/roompost/adapter/in/web/AttendanceCheckDeleteApiTest.java b/src/test/java/konkuk/thip/roompost/adapter/in/web/AttendanceCheckDeleteApiTest.java index 19ee0b192..d9274100a 100644 --- a/src/test/java/konkuk/thip/roompost/adapter/in/web/AttendanceCheckDeleteApiTest.java +++ b/src/test/java/konkuk/thip/roompost/adapter/in/web/AttendanceCheckDeleteApiTest.java @@ -5,7 +5,7 @@ import konkuk.thip.book.adapter.out.persistence.repository.BookJpaRepository; import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.room.domain.value.Category; diff --git a/src/test/java/konkuk/thip/roompost/adapter/in/web/AttendanceCheckShowApiTest.java b/src/test/java/konkuk/thip/roompost/adapter/in/web/AttendanceCheckShowApiTest.java index ed944bdd0..949369b07 100644 --- a/src/test/java/konkuk/thip/roompost/adapter/in/web/AttendanceCheckShowApiTest.java +++ b/src/test/java/konkuk/thip/roompost/adapter/in/web/AttendanceCheckShowApiTest.java @@ -5,7 +5,7 @@ import konkuk.thip.book.adapter.out.persistence.repository.BookJpaRepository; import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.room.domain.value.Category; diff --git a/src/test/java/konkuk/thip/roompost/adapter/in/web/RecordCreateControllerTest.java b/src/test/java/konkuk/thip/roompost/adapter/in/web/RecordCreateControllerTest.java index 23e92f679..dd779b8e0 100644 --- a/src/test/java/konkuk/thip/roompost/adapter/in/web/RecordCreateControllerTest.java +++ b/src/test/java/konkuk/thip/roompost/adapter/in/web/RecordCreateControllerTest.java @@ -11,7 +11,7 @@ import konkuk.thip.roompost.adapter.out.persistence.repository.record.RecordJpaRepository; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.adapter.out.jpa.RoomParticipantJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; diff --git a/src/test/java/konkuk/thip/roompost/adapter/in/web/RecordDeleteApiTest.java b/src/test/java/konkuk/thip/roompost/adapter/in/web/RecordDeleteApiTest.java index b67553006..1f150ee4b 100644 --- a/src/test/java/konkuk/thip/roompost/adapter/in/web/RecordDeleteApiTest.java +++ b/src/test/java/konkuk/thip/roompost/adapter/in/web/RecordDeleteApiTest.java @@ -11,7 +11,7 @@ import konkuk.thip.roompost.adapter.out.jpa.RecordJpaEntity; import konkuk.thip.roompost.adapter.out.persistence.repository.record.RecordJpaRepository; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; diff --git a/src/test/java/konkuk/thip/roompost/adapter/in/web/RecordPinApiTest.java b/src/test/java/konkuk/thip/roompost/adapter/in/web/RecordPinApiTest.java index 647b9c78c..dab31cfc2 100644 --- a/src/test/java/konkuk/thip/roompost/adapter/in/web/RecordPinApiTest.java +++ b/src/test/java/konkuk/thip/roompost/adapter/in/web/RecordPinApiTest.java @@ -7,7 +7,7 @@ import konkuk.thip.roompost.adapter.out.jpa.RecordJpaEntity; import konkuk.thip.roompost.adapter.out.persistence.repository.record.RecordJpaRepository; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; diff --git a/src/test/java/konkuk/thip/roompost/adapter/in/web/RecordUpdateApiTest.java b/src/test/java/konkuk/thip/roompost/adapter/in/web/RecordUpdateApiTest.java index eeea8ad1c..5565fe947 100644 --- a/src/test/java/konkuk/thip/roompost/adapter/in/web/RecordUpdateApiTest.java +++ b/src/test/java/konkuk/thip/roompost/adapter/in/web/RecordUpdateApiTest.java @@ -6,7 +6,7 @@ import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.adapter.out.jpa.RoomParticipantJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.room.domain.value.Category; diff --git a/src/test/java/konkuk/thip/roompost/adapter/in/web/RoomPostSearchApiTest.java b/src/test/java/konkuk/thip/roompost/adapter/in/web/RoomPostSearchApiTest.java index c84b71227..948427563 100644 --- a/src/test/java/konkuk/thip/roompost/adapter/in/web/RoomPostSearchApiTest.java +++ b/src/test/java/konkuk/thip/roompost/adapter/in/web/RoomPostSearchApiTest.java @@ -10,11 +10,11 @@ import konkuk.thip.roompost.adapter.out.persistence.repository.record.RecordJpaRepository; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.adapter.out.jpa.RoomParticipantJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; -import konkuk.thip.user.adapter.out.jpa.UserRole; +import konkuk.thip.user.domain.value.UserRole; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import konkuk.thip.roompost.adapter.out.jpa.VoteItemJpaEntity; import konkuk.thip.roompost.adapter.out.jpa.VoteJpaEntity; diff --git a/src/test/java/konkuk/thip/roompost/adapter/in/web/VoteApiTest.java b/src/test/java/konkuk/thip/roompost/adapter/in/web/VoteApiTest.java index b470527ab..d180f4b30 100644 --- a/src/test/java/konkuk/thip/roompost/adapter/in/web/VoteApiTest.java +++ b/src/test/java/konkuk/thip/roompost/adapter/in/web/VoteApiTest.java @@ -5,7 +5,7 @@ import konkuk.thip.book.adapter.out.persistence.repository.BookJpaRepository; import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.room.domain.value.Category; diff --git a/src/test/java/konkuk/thip/roompost/adapter/in/web/VoteCreateApiTest.java b/src/test/java/konkuk/thip/roompost/adapter/in/web/VoteCreateApiTest.java index e16bb8c0b..5cc332584 100644 --- a/src/test/java/konkuk/thip/roompost/adapter/in/web/VoteCreateApiTest.java +++ b/src/test/java/konkuk/thip/roompost/adapter/in/web/VoteCreateApiTest.java @@ -6,7 +6,7 @@ import konkuk.thip.book.adapter.out.persistence.repository.BookJpaRepository; import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.room.domain.value.Category; diff --git a/src/test/java/konkuk/thip/roompost/adapter/in/web/VoteDeleteApiTest.java b/src/test/java/konkuk/thip/roompost/adapter/in/web/VoteDeleteApiTest.java index f57614cea..0ed2a6af6 100644 --- a/src/test/java/konkuk/thip/roompost/adapter/in/web/VoteDeleteApiTest.java +++ b/src/test/java/konkuk/thip/roompost/adapter/in/web/VoteDeleteApiTest.java @@ -8,7 +8,7 @@ import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.post.adapter.out.persistence.PostLikeJpaRepository; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.room.domain.value.Category; diff --git a/src/test/java/konkuk/thip/roompost/adapter/in/web/VoteUpdateApiTest.java b/src/test/java/konkuk/thip/roompost/adapter/in/web/VoteUpdateApiTest.java index 4c287d1f9..76ee76306 100644 --- a/src/test/java/konkuk/thip/roompost/adapter/in/web/VoteUpdateApiTest.java +++ b/src/test/java/konkuk/thip/roompost/adapter/in/web/VoteUpdateApiTest.java @@ -6,7 +6,7 @@ import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.adapter.out.jpa.RoomParticipantJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.room.domain.value.Category; diff --git a/src/test/java/konkuk/thip/roompost/application/service/VoteCreateServiceTest.java b/src/test/java/konkuk/thip/roompost/application/service/VoteCreateServiceTest.java index abcc74362..dbb3603fd 100644 --- a/src/test/java/konkuk/thip/roompost/application/service/VoteCreateServiceTest.java +++ b/src/test/java/konkuk/thip/roompost/application/service/VoteCreateServiceTest.java @@ -5,7 +5,7 @@ import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.adapter.out.jpa.RoomParticipantJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.room.domain.value.Category; diff --git a/src/test/java/konkuk/thip/user/adapter/in/web/UserFollowApiTest.java b/src/test/java/konkuk/thip/user/adapter/in/web/UserFollowApiTest.java index 57b281484..77814ec56 100644 --- a/src/test/java/konkuk/thip/user/adapter/in/web/UserFollowApiTest.java +++ b/src/test/java/konkuk/thip/user/adapter/in/web/UserFollowApiTest.java @@ -3,7 +3,7 @@ import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.user.adapter.out.jpa.FollowingJpaEntity; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; -import konkuk.thip.user.adapter.out.jpa.UserRole; +import konkuk.thip.user.domain.value.UserRole; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import konkuk.thip.user.adapter.out.persistence.repository.following.FollowingJpaRepository; import konkuk.thip.user.domain.value.Alias; diff --git a/src/test/java/konkuk/thip/user/adapter/in/web/UserReactionApiTest.java b/src/test/java/konkuk/thip/user/adapter/in/web/UserReactionApiTest.java index 494a22ab7..91d61fad3 100644 --- a/src/test/java/konkuk/thip/user/adapter/in/web/UserReactionApiTest.java +++ b/src/test/java/konkuk/thip/user/adapter/in/web/UserReactionApiTest.java @@ -11,7 +11,7 @@ import konkuk.thip.post.adapter.out.jpa.PostLikeJpaEntity; import konkuk.thip.post.adapter.out.persistence.PostLikeJpaRepository; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomParticipantRole; +import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.room.domain.value.Category; diff --git a/src/test/java/konkuk/thip/user/adapter/in/web/UserSearchApiTest.java b/src/test/java/konkuk/thip/user/adapter/in/web/UserSearchApiTest.java index 92842ba8c..2f4a1946d 100644 --- a/src/test/java/konkuk/thip/user/adapter/in/web/UserSearchApiTest.java +++ b/src/test/java/konkuk/thip/user/adapter/in/web/UserSearchApiTest.java @@ -2,7 +2,7 @@ import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.recentSearch.adapter.out.jpa.RecentSearchJpaEntity; -import konkuk.thip.recentSearch.adapter.out.jpa.RecentSearchType; +import konkuk.thip.recentSearch.domain.value.RecentSearchType; import konkuk.thip.recentSearch.adapter.out.persistence.repository.RecentSearchJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; diff --git a/src/test/java/konkuk/thip/user/adapter/in/web/UserUpdateApiTest.java b/src/test/java/konkuk/thip/user/adapter/in/web/UserUpdateApiTest.java index 04225af42..9a929dc52 100644 --- a/src/test/java/konkuk/thip/user/adapter/in/web/UserUpdateApiTest.java +++ b/src/test/java/konkuk/thip/user/adapter/in/web/UserUpdateApiTest.java @@ -4,7 +4,7 @@ import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.user.adapter.in.web.request.UserUpdateRequest; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; -import konkuk.thip.user.adapter.out.jpa.UserRole; +import konkuk.thip.user.domain.value.UserRole; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import konkuk.thip.user.domain.value.Alias; import org.junit.jupiter.api.AfterEach; diff --git a/src/test/java/konkuk/thip/user/adapter/in/web/UserVerifyNicknameControllerTest.java b/src/test/java/konkuk/thip/user/adapter/in/web/UserVerifyNicknameControllerTest.java index fa56158ec..99901b3d6 100644 --- a/src/test/java/konkuk/thip/user/adapter/in/web/UserVerifyNicknameControllerTest.java +++ b/src/test/java/konkuk/thip/user/adapter/in/web/UserVerifyNicknameControllerTest.java @@ -23,7 +23,7 @@ import java.time.LocalDate; import static konkuk.thip.common.exception.code.ErrorCode.API_INVALID_PARAM; -import static konkuk.thip.user.adapter.out.jpa.UserRole.USER; +import static konkuk.thip.user.domain.value.UserRole.USER; import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.Matchers.containsString; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; diff --git a/src/test/java/konkuk/thip/user/adapter/out/jpa/UserJpaEntityTest.java b/src/test/java/konkuk/thip/user/adapter/out/jpa/UserJpaEntityTest.java index 832e43af2..5f9a23571 100644 --- a/src/test/java/konkuk/thip/user/adapter/out/jpa/UserJpaEntityTest.java +++ b/src/test/java/konkuk/thip/user/adapter/out/jpa/UserJpaEntityTest.java @@ -5,6 +5,7 @@ import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import konkuk.thip.user.domain.value.Alias; +import konkuk.thip.user.domain.value.UserRole; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; From 6504d3df2bc8c51f8a5ace5e9d8508e9f9dd97ef Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 13:50:12 +0900 Subject: [PATCH 65/93] =?UTF-8?q?[fix]=20=EB=B0=A9=20=EC=8B=9C=EC=9E=91=20?= =?UTF-8?q?=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EB=B0=9C=ED=96=89=EC=8B=9C=20?= =?UTF-8?q?=EC=9E=98=EB=AA=BB=EB=90=9C=20=EB=8C=80=EC=83=81=20id=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=20=EC=88=98=EC=A0=95=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/room/application/service/RoomStateChangeService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java b/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java index eca383d89..b1e46a151 100644 --- a/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java +++ b/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java @@ -55,7 +55,7 @@ private void sendNotifications() { for (Room room : targetRooms) { List targetUsers = roomParticipantCommandPort.findAllByRoomId(room.getId()); for (RoomParticipant participant : targetUsers) { - roomEventCommandPort.publishRoomActivityStartedEvent(participant.getId(), room.getId(), room.getTitle()); + roomEventCommandPort.publishRoomActivityStartedEvent(participant.getUserId(), room.getId(), room.getTitle()); } } } From 2991db361bbb13e28b1aca77cf055f34f9e72191 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 13:52:05 +0900 Subject: [PATCH 66/93] =?UTF-8?q?[refactor]=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20switch=EB=AC=B8=20=EC=A0=9C=EA=B1=B0=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/application/service/handler/PostHandler.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/konkuk/thip/post/application/service/handler/PostHandler.java b/src/main/java/konkuk/thip/post/application/service/handler/PostHandler.java index 978361b0d..c7ece4d65 100644 --- a/src/main/java/konkuk/thip/post/application/service/handler/PostHandler.java +++ b/src/main/java/konkuk/thip/post/application/service/handler/PostHandler.java @@ -37,9 +37,10 @@ public void updatePost(PostType type, CountUpdatable post) { } public PostQueryDto getPostQueryDto(PostType type, Long postId) { - return switch (type) { - case FEED -> feedCommandPort.getPostQueryDtoById(postId); - default -> recordCommandPort.getPostQueryDtoById(postId); - }; + if (type == PostType.FEED) { + return feedCommandPort.getPostQueryDtoById(postId); + } + + return recordCommandPort.getPostQueryDtoById(postId); } } From 868965016db26724ab04bd4a9e37bd13b4442a7a Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 13:57:49 +0900 Subject: [PATCH 67/93] =?UTF-8?q?[refactor]=20Param=20=EB=B0=94=EC=9D=B8?= =?UTF-8?q?=EB=94=A9=20=EC=B6=94=EA=B0=80=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/out/persistence/repository/UserJpaRepository.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/konkuk/thip/user/adapter/out/persistence/repository/UserJpaRepository.java b/src/main/java/konkuk/thip/user/adapter/out/persistence/repository/UserJpaRepository.java index 7e2f81c4a..9d9de3449 100644 --- a/src/main/java/konkuk/thip/user/adapter/out/persistence/repository/UserJpaRepository.java +++ b/src/main/java/konkuk/thip/user/adapter/out/persistence/repository/UserJpaRepository.java @@ -3,6 +3,7 @@ import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import java.util.List; import java.util.Optional; @@ -23,5 +24,5 @@ public interface UserJpaRepository extends JpaRepository, U boolean existsByOauth2Id(String oauth2Id); @Query("SELECT f.userJpaEntity FROM FollowingJpaEntity f WHERE f.followingUserJpaEntity.userId = :userId") - List findAllFollowersByUserId(Long userId); + List findAllFollowersByUserId(@Param("userId") Long userId); } From c9bc6c7d4cb800fad607917196ab8c3c2bc414bf Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 13:58:05 +0900 Subject: [PATCH 68/93] =?UTF-8?q?[refactor]=20=EB=AA=A8=EC=9E=84=EB=B0=A9?= =?UTF-8?q?=20=EB=8C=93=EA=B8=80=20=EC=A2=8B=EC=95=84=EC=9A=94=20=EC=8B=9C?= =?UTF-8?q?=20postType=20=EB=9D=BC=EC=9A=B0=ED=8A=B8=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/comment/application/service/CommentLikeService.java | 2 +- .../message/adapter/out/event/RoomEventPublisherAdapter.java | 3 ++- .../konkuk/thip/message/adapter/out/event/dto/RoomEvents.java | 2 +- .../message/application/port/out/RoomEventCommandPort.java | 2 +- .../application/service/RoomNotificationDispatchService.java | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/konkuk/thip/comment/application/service/CommentLikeService.java b/src/main/java/konkuk/thip/comment/application/service/CommentLikeService.java index 45899d8e2..4fc0c4725 100644 --- a/src/main/java/konkuk/thip/comment/application/service/CommentLikeService.java +++ b/src/main/java/konkuk/thip/comment/application/service/CommentLikeService.java @@ -77,7 +77,7 @@ private void sendNotifications(CommentIsLikeCommand command, Comment comment) { } if (comment.getPostType() == PostType.RECORD || comment.getPostType() == PostType.VOTE) { PostQueryDto postQueryDto = postHandler.getPostQueryDto(comment.getPostType(), comment.getTargetPostId()); - roomEventCommandPort.publishRoomCommentLikedEvent(comment.getCreatorId(), actorUser.getId(), actorUser.getNickname(), postQueryDto.roomId(), postQueryDto.page(), postQueryDto.postId()); + roomEventCommandPort.publishRoomCommentLikedEvent(comment.getCreatorId(), actorUser.getId(), actorUser.getNickname(), postQueryDto.roomId(), postQueryDto.page(), postQueryDto.postId(), postQueryDto.postType()); } } } diff --git a/src/main/java/konkuk/thip/message/adapter/out/event/RoomEventPublisherAdapter.java b/src/main/java/konkuk/thip/message/adapter/out/event/RoomEventPublisherAdapter.java index 9d0e31380..c8cf0c5d7 100644 --- a/src/main/java/konkuk/thip/message/adapter/out/event/RoomEventPublisherAdapter.java +++ b/src/main/java/konkuk/thip/message/adapter/out/event/RoomEventPublisherAdapter.java @@ -84,7 +84,7 @@ public void publishRoomJoinEventToHost(Long hostUserId, Long roomId, String room @Override public void publishRoomCommentLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, - Long roomId, Integer page, Long postId) { + Long roomId, Integer page, Long postId, String postType) { publisher.publishEvent(RoomEvents.RoomCommentLikedEvent.builder() .targetUserId(targetUserId) .actorUserId(actorUserId) @@ -92,6 +92,7 @@ public void publishRoomCommentLikedEvent(Long targetUserId, Long actorUserId, St .roomId(roomId) .page(page) .postId(postId) + .postType(postType) .build()); } diff --git a/src/main/java/konkuk/thip/message/adapter/out/event/dto/RoomEvents.java b/src/main/java/konkuk/thip/message/adapter/out/event/dto/RoomEvents.java index 4aa6cc66d..bdc076f93 100644 --- a/src/main/java/konkuk/thip/message/adapter/out/event/dto/RoomEvents.java +++ b/src/main/java/konkuk/thip/message/adapter/out/event/dto/RoomEvents.java @@ -37,7 +37,7 @@ public record RoomJoinRequestedToOwnerEvent(Long ownerUserId, Long roomId, Strin // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ์˜ ๋‚˜์˜ ๋Œ“๊ธ€์ด ์ข‹์•„์š”๋ฅผ ๋ฐ›๋Š” ๊ฒฝ์šฐ @Builder public record RoomCommentLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, - Long roomId, Integer page, Long postId) {} + Long roomId, Integer page, Long postId, String postType) {} // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ์˜ ๋‚˜์˜ ๊ธฐ๋ก์ด ์ข‹์•„์š”๋ฅผ ๋ฐ›๋Š” ๊ฒฝ์šฐ @Builder diff --git a/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java b/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java index f4486321e..b840969a1 100644 --- a/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java +++ b/src/main/java/konkuk/thip/message/application/port/out/RoomEventCommandPort.java @@ -26,7 +26,7 @@ void publishRoomJoinEventToHost(Long hostUserId, Long roomId, String roomTitle, // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ์˜ ๋‚˜์˜ ๋Œ“๊ธ€์ด ์ข‹์•„์š”๋ฅผ ๋ฐ›๋Š” ๊ฒฝ์šฐ void publishRoomCommentLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, - Long roomId, Integer page, Long postId); + Long roomId, Integer page, Long postId, String postType); // ๋‚ด๊ฐ€ ์ฐธ์—ฌํ•œ ๋ชจ์ž„๋ฐฉ ์•ˆ์˜ ๋‚˜์˜ ๊ธฐ๋ก/ํˆฌํ‘œ๊ฐ€ ์ข‹์•„์š”๋ฅผ ๋ฐ›๋Š” ๊ฒฝ์šฐ void publishRoomPostLikedEvent(Long targetUserId, Long actorUserId, String actorUsername, diff --git a/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java b/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java index bb6c1b1ab..44d1c42bc 100644 --- a/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java +++ b/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java @@ -145,7 +145,7 @@ public void handleRoomCommentLiked(final RoomEvents.RoomCommentLikedEvent event) "page", String.valueOf(event.page()), "type", "group", "postId", String.valueOf(event.postId()), - "postType", "RECORD"); + "postType", String.valueOf(event.postType())); msgs.add(m); tk.add(t.getFcmToken()); dev.add(t.getDeviceId()); } firebasePort.sendBatch(msgs, tk, dev); From 42f62195ee1c35024f55fdb9568b53d156856d88 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 14:04:56 +0900 Subject: [PATCH 69/93] =?UTF-8?q?[feat]=20=ED=91=B8=EC=89=AC=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EB=84=A4=EB=B9=84=EA=B2=8C=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EB=9D=BC=EC=9A=B0=ED=8A=B8=20=EB=B6=84=EA=B8=B0=20=EA=B5=AC?= =?UTF-8?q?=EC=B2=B4=ED=99=94=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/RoomNotificationDispatchService.java | 10 +++++----- .../java/konkuk/thip/message/domain/MessageRoute.java | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java b/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java index 44d1c42bc..629ffda14 100644 --- a/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java +++ b/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java @@ -38,7 +38,7 @@ public void handleRoomPostCommented(final RoomEvents.RoomPostCommentedEvent even for (FcmToken t : tokens) { Message m = buildMessage(t.getFcmToken(), notification, - MessageRoute.ROOM_RECORD_DETAIL, + MessageRoute.ROOM_POST_DETAIL, "roomId", String.valueOf(event.roomId()), "page", String.valueOf(event.page()), "type", "group", @@ -140,7 +140,7 @@ public void handleRoomCommentLiked(final RoomEvents.RoomCommentLikedEvent event) for (FcmToken t : tokens) { Message m = buildMessage(t.getFcmToken(), notification, - MessageRoute.ROOM_RECORD_DETAIL, + MessageRoute.ROOM_POST_DETAIL, "roomId", String.valueOf(event.roomId()), "page", String.valueOf(event.page()), "type", "group", @@ -165,12 +165,12 @@ public void handleRoomPostLiked(final RoomEvents.RoomPostLikedEvent event) { for (FcmToken t : tokens) { Message m = buildMessage(t.getFcmToken(), notification, - MessageRoute.ROOM_RECORD_DETAIL, + MessageRoute.ROOM_POST_DETAIL, "roomId", String.valueOf(event.roomId()), "page", String.valueOf(event.page()), "type", "group", "postId", String.valueOf(event.postId()), - "postType", "RECORD"); + "postType", String.valueOf(event.postType())); msgs.add(m); tk.add(t.getFcmToken()); dev.add(t.getDeviceId()); } firebasePort.sendBatch(msgs, tk, dev); @@ -190,7 +190,7 @@ public void handleRoomPostCommentReplied(RoomEvents.RoomPostCommentRepliedEvent for (FcmToken t : tokens) { Message m = buildMessage(t.getFcmToken(), notification, - MessageRoute.ROOM_RECORD_DETAIL, + MessageRoute.ROOM_POST_DETAIL, "roomId", String.valueOf(e.roomId()), "page", String.valueOf(e.page()), "type", "group", diff --git a/src/main/java/konkuk/thip/message/domain/MessageRoute.java b/src/main/java/konkuk/thip/message/domain/MessageRoute.java index 457aaa924..d664ecc8f 100644 --- a/src/main/java/konkuk/thip/message/domain/MessageRoute.java +++ b/src/main/java/konkuk/thip/message/domain/MessageRoute.java @@ -13,6 +13,7 @@ public enum MessageRoute { // ROOM ROOM_MAIN("ROOM_MAIN"), // ํŠน์ • ๋ชจ์ž„๋ฐฉ ๋ฉ”์ธ ํ™”๋ฉด์œผ๋กœ ์ด๋™ ROOM_DETAIL("ROOM_DETAIL"), // ํŠน์ • ๋ชจ์ž„ ์ƒ์„ธ์ •๋ณด ํ™”๋ฉด์œผ๋กœ ์ด๋™ + ROOM_POST_DETAIL("ROOM_POST_DETAIL"), // ํŠน์ • ๋ชจ์ž„ ๊ฒŒ์‹œ๊ธ€ ์ƒ์„ธ ํ™”๋ฉด์œผ๋กœ ์ด๋™ -> PostType์œผ๋กœ ํˆฌํ‘œ์ธ์ง€ ๊ธฐ๋ก์ธ์ง€ ํŒ๋‹จ ROOM_RECORD_DETAIL("ROOM_RECORD_DETAIL"), // ํŠน์ • ๋ชจ์ž„ ๊ธฐ๋ก ์ƒ์„ธ ํ™”๋ฉด์œผ๋กœ ์ด๋™ (๊ธฐ๋ก์žฅ ์กฐํšŒ - ํŽ˜์ด์ง€ ํ•„ํ„ฐ ๊ฑธ๋ฆฐ์ฑ„๋กœ) ROOM_VOTE_DETAIL("ROOM_VOTE_DETAIL"); // ํŠน์ • ๋ชจ์ž„ ํˆฌํ‘œ ์ƒ์„ธ ํ™”๋ฉด์œผ๋กœ ์ด๋™ (ํˆฌํ‘œ ์กฐํšŒ - ํŽ˜์ด์ง€ ํ•„ํ„ฐ ๊ฑธ๋ฆฐ์ฑ„๋กœ) From 5326aadfea9e26a364cf5dc5a5f772be1d71541d Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 14:18:06 +0900 Subject: [PATCH 70/93] =?UTF-8?q?[fix]=20=EB=8B=B5=EA=B8=80=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=ED=91=B8=EC=89=AC=EC=95=8C=EB=A6=BC=20=EB=8C=80?= =?UTF-8?q?=EC=83=81=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/CommentCreateService.java | 39 +++++++++++-------- .../RoomNotificationDispatchService.java | 4 +- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/main/java/konkuk/thip/comment/application/service/CommentCreateService.java b/src/main/java/konkuk/thip/comment/application/service/CommentCreateService.java index 25d8ab18e..57b808ce2 100644 --- a/src/main/java/konkuk/thip/comment/application/service/CommentCreateService.java +++ b/src/main/java/konkuk/thip/comment/application/service/CommentCreateService.java @@ -24,6 +24,7 @@ import org.springframework.transaction.annotation.Transactional; import static konkuk.thip.common.exception.code.ErrorCode.INVALID_COMMENT_CREATE; +import static konkuk.thip.post.domain.PostType.*; @Service @@ -48,15 +49,17 @@ public CommentCreateResponse createComment(CommentCreateCommand command) { // 1. ๋Œ“๊ธ€/๋‹ต๊ธ€ ์ƒ์„ฑ ์„ ํ–‰๊ฒ€์ฆ ๋ฐ ์ž‘์„ฑํ•˜๋ ค๋Š” ๊ฒŒ์‹œ๊ธ€ ํƒ€์ž… ๊ฒ€์ฆ Comment.validateCommentCreate(command.isReplyRequest(), command.parentId()); - PostType type = PostType.from(command.postType()); + PostType type = from(command.postType()); // 2. ๊ฒŒ์‹œ๋ฌผ ํƒ€์ž…์— ๋งž๊ฒŒ ์กฐํšŒ CountUpdatable post = postHandler.findPost(type, command.postId()); // 2-1. ๊ฒŒ์‹œ๊ธ€ ํƒ€์ž…์— ๋”ฐ๋ฅธ ๋Œ“๊ธ€ ์ƒ์„ฑ ๊ถŒํ•œ ๊ฒ€์ฆ commentAuthorizationValidator.validateUserCanAccessPostForComment(type, post, command.userId()); - // 2-2. ํ‘ธ์‰ฌ ์•Œ๋ฆผ ์ „์†ก - sendNotifications(command, type, post); + // 2-2. ๋Œ“๊ธ€ ์ƒ์„ฑ ํ‘ธ์‰ฌ ์•Œ๋ฆผ ์ „์†ก (๊ฒŒ์‹œ๊ธ€ ์ž‘์„ฑ์ž์—๊ฒŒ) + PostQueryDto postQueryDto = postHandler.getPostQueryDto(type, post.getId()); + User actorUser = userCommandPort.findById(command.userId()); + sendNotificationsToPostWriter(postQueryDto, actorUser); // 3. ๋Œ“๊ธ€ ์ƒ์„ฑ Long savedCommentId = createCommentDomain(command); @@ -73,6 +76,10 @@ public CommentCreateResponse createComment(CommentCreateCommand command) { if (command.isReplyRequest()) { // ๋ถ€๋ชจ ๋Œ“๊ธ€ ์กฐํšŒ CommentQueryDto parentCommentDto = commentQueryPort.findRootCommentById(command.parentId()); + + // ๋‹ต๊ธ€ ์ƒ์„ฑ ํ‘ธ์‰ฌ ์•Œ๋ฆผ ์ „์†ก (๋ถ€๋ชจ ๋Œ“๊ธ€ ์ž‘์„ฑ์ž์—๊ฒŒ) + sendNotificationsToParentCommentWriter(postQueryDto, parentCommentDto, actorUser); + // ์‚ฌ์šฉ์ž ๋ถ€๋ชจ ๋Œ“๊ธ€ ์ข‹์•„์š” ์—ฌ๋ถ€ ์กฐํšŒ boolean isLikedParentComment = commentLikeQueryPort.isLikedCommentByUser(command.userId(),parentCommentDto.commentId()); @@ -84,23 +91,23 @@ public CommentCreateResponse createComment(CommentCreateCommand command) { } } - private void sendNotifications(CommentCreateCommand command, PostType type, CountUpdatable post) { - PostQueryDto postQueryDto = postHandler.getPostQueryDto(type, post.getId()); - User actorUser = userCommandPort.findById(command.userId()); - if (type == PostType.FEED) { + private void sendNotificationsToPostWriter(PostQueryDto postQueryDto, User actorUser) { + if (postQueryDto.postType().equals(FEED.getType())) { // ํ”ผ๋“œ ๋Œ“๊ธ€ ์•Œ๋ฆผ ์ด๋ฒคํŠธ ๋ฐœํ–‰ feedEventCommandPort.publishFeedCommentedEvent(postQueryDto.creatorId(), actorUser.getId(), actorUser.getNickname(), postQueryDto.postId()); - if (command.isReplyRequest()){ - // ํ”ผ๋“œ ๋‹ต๊ธ€ ์•Œ๋ฆผ ์ด๋ฒคํŠธ ๋ฐœํ–‰ - feedEventCommandPort.publishFeedRepliedEvent(postQueryDto.creatorId(), actorUser.getId(), actorUser.getNickname(), postQueryDto.postId()); - } - } else if (type == PostType.RECORD || type == PostType.VOTE) { + } else if (postQueryDto.postType().equals(RECORD.getType()) || postQueryDto.postType().equals(VOTE.getType())) { // ๋ชจ์ž„๋ฐฉ ๊ฒŒ์‹œ๊ธ€ ๋Œ“๊ธ€ ์•Œ๋ฆผ ์ด๋ฒคํŠธ ๋ฐœํ–‰ roomEventCommandPort.publishRoomPostCommentedEvent(postQueryDto.creatorId(), actorUser.getId(), actorUser.getNickname(), postQueryDto.roomId(), postQueryDto.page(), postQueryDto.postId(), postQueryDto.postType()); - if (command.isReplyRequest()){ - // ๋ชจ์ž„๋ฐฉ ๊ฒŒ์‹œ๊ธ€ ๋‹ต๊ธ€ ์•Œ๋ฆผ ์ด๋ฒคํŠธ ๋ฐœํ–‰ - roomEventCommandPort.publishRoomPostCommentRepliedEvent(postQueryDto.creatorId(), actorUser.getId(), actorUser.getNickname(), postQueryDto.roomId(), postQueryDto.page(), postQueryDto.postId(), postQueryDto.postType()); - } + } + } + + private void sendNotificationsToParentCommentWriter(PostQueryDto postQueryDto, CommentQueryDto parentCommentDto, User actorUser) { + if (postQueryDto.postType().equals(FEED.getType())) { + // ํ”ผ๋“œ ๋‹ต๊ธ€ ์•Œ๋ฆผ ์ด๋ฒคํŠธ ๋ฐœํ–‰ + feedEventCommandPort.publishFeedRepliedEvent(parentCommentDto.creatorId(), actorUser.getId(), actorUser.getNickname(), postQueryDto.postId()); + } else if (postQueryDto.postType().equals(RECORD.getType()) || postQueryDto.postType().equals(VOTE.getType())) { + // ๋ชจ์ž„๋ฐฉ ๊ฒŒ์‹œ๊ธ€ ๋‹ต๊ธ€ ์•Œ๋ฆผ ์ด๋ฒคํŠธ ๋ฐœํ–‰ + roomEventCommandPort.publishRoomPostCommentRepliedEvent(parentCommentDto.creatorId(), actorUser.getId(), actorUser.getNickname(), postQueryDto.roomId(), postQueryDto.page(), postQueryDto.postId(), postQueryDto.postType()); } } diff --git a/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java b/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java index 629ffda14..83bb127ee 100644 --- a/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java +++ b/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java @@ -43,7 +43,7 @@ public void handleRoomPostCommented(final RoomEvents.RoomPostCommentedEvent even "page", String.valueOf(event.page()), "type", "group", "postId", String.valueOf(event.postId()), - "postType", event.postType()); + "postType", String.valueOf(event.postType())); msgs.add(m); tk.add(t.getFcmToken()); dev.add(t.getDeviceId()); } @@ -195,7 +195,7 @@ public void handleRoomPostCommentReplied(RoomEvents.RoomPostCommentRepliedEvent "page", String.valueOf(e.page()), "type", "group", "postId", String.valueOf(e.postId()), - "postType", e.postType()); + "postType", String.valueOf(e.postType())); msgs.add(m); tk.add(t.getFcmToken()); dev.add(t.getDeviceId()); } From 1a45cc54308791d86b411325f5e106e46f211b72 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 14:24:10 +0900 Subject: [PATCH 71/93] [refactor] FB key path hidden (#289) --- .github/workflows/cd-workflow-dev.yml | 2 +- .github/workflows/cd-workflow-prod.yml | 2 +- .github/workflows/ci-workflow.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cd-workflow-dev.yml b/.github/workflows/cd-workflow-dev.yml index 4d9ed0c4f..41969f200 100644 --- a/.github/workflows/cd-workflow-dev.yml +++ b/.github/workflows/cd-workflow-dev.yml @@ -11,7 +11,7 @@ permissions: env: RESOURCE_PATH: src/main/resources COMPOSE_PATH: /home/ec2-user/compose - FIREBASE_KEY_PATH: src/main/resources/firebase + FIREBASE_KEY_PATH: ${{ secrets.FIREBASE_KEY_PATH }} APP_PORT: 8000 jobs: diff --git a/.github/workflows/cd-workflow-prod.yml b/.github/workflows/cd-workflow-prod.yml index 203cea8f6..52117eb46 100644 --- a/.github/workflows/cd-workflow-prod.yml +++ b/.github/workflows/cd-workflow-prod.yml @@ -11,7 +11,7 @@ permissions: env: RESOURCE_PATH: src/main/resources COMPOSE_PATH: /home/ec2-user/compose - FIREBASE_KEY_PATH: src/main/resources/firebase + FIREBASE_KEY_PATH: ${{ secrets.FIREBASE_KEY_PATH }} APP_PORT: 8000 jobs: diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index 11fc460d3..615cc801c 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -14,7 +14,7 @@ permissions: env: RESOURCE_PATH: src/main/resources TEST_RESOURCE_PATH: src/test/resources - FIREBASE_KEY_PATH: src/main/resources/firebase + FIREBASE_KEY_PATH: ${{ secrets.FIREBASE_KEY_PATH }} jobs: build: From 2dccc8afb20dfc6249ff4e5c7a5bdd347486681f Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 14:29:31 +0900 Subject: [PATCH 72/93] =?UTF-8?q?[refactor]=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20api=20path=20=EC=88=98=EC=A0=95=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/in/web/NotificationCommandController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java b/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java index 012887092..c3d1d0ec8 100644 --- a/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java +++ b/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java @@ -29,7 +29,7 @@ public class NotificationCommandController { private final FcmDeleteUseCase fcmDeleteUseCase; @Operation(summary = "FCM ํ† ํฐ ๋“ฑ๋ก", description = "์‚ฌ์šฉ์ž์˜ FCM ํ† ํฐ์„ ์„œ๋ฒ„์— ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด ํ† ํฐ์ด ์žˆ๋‹ค๋ฉด deviceId ๊ธฐ์ค€์œผ๋กœ ํ† ํฐ์„ ๊ฐฑ์‹ ํ•ฉ๋‹ˆ๋‹ค.") - @PostMapping("/fcm-tokens") + @PostMapping("/notifications/fcm-tokens") @ExceptionDescription(FCM_TOKEN_REGISTER) public BaseResponse registerFcmToken( @RequestBody @Valid FcmTokenRegisterRequest request, @@ -50,7 +50,7 @@ public BaseResponse updatePushNotificationSet FcmTokenEnableStateChangeResponse.of(fcmEnableStateChangeUseCase.changeEnableState(request.toCommand(userId)))); } - @DeleteMapping("/fcm-tokens") + @DeleteMapping("/notifications/fcm-tokens") @Operation(summary = "FCM ํ† ํฐ ์‚ญ์ œ", description = "์‚ฌ์šฉ์ž์˜ FCM ํ† ํฐ์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.") public BaseResponse deleteFcmToken( @RequestBody @Valid FcmTokenDeleteRequest request, From 07e6f64e831dc697457ad23dd8de4b683a0e2e53 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 14:40:14 +0900 Subject: [PATCH 73/93] =?UTF-8?q?[refactor]=20Fcm=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=EC=8B=9C=20=EC=86=8C=EC=9C=A0=EC=9E=90=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/konkuk/thip/common/exception/code/ErrorCode.java | 2 +- .../thip/common/swagger/SwaggerResponseDescription.java | 7 ++++++- .../adapter/in/web/NotificationCommandController.java | 4 +++- .../notification/application/service/FcmDeleteService.java | 5 ++++- .../java/konkuk/thip/notification/domain/FcmToken.java | 6 +++++- 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java b/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java index d4f2b4b47..09c05ec9b 100644 --- a/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java +++ b/src/main/java/konkuk/thip/common/exception/code/ErrorCode.java @@ -216,7 +216,7 @@ public enum ErrorCode implements ResponseCode { */ FCM_TOKEN_NOT_FOUND(HttpStatus.NOT_FOUND, 200000, "์กด์žฌํ•˜์ง€ ์•Š๋Š” FCM TOKEN ์ž…๋‹ˆ๋‹ค."), FCM_TOKEN_ENABLED_STATE_ALREADY(HttpStatus.BAD_REQUEST, 200001, "์š”์ฒญํ•œ ์ƒํƒœ๋กœ ์ด๋ฏธ ํ‘ธ์‰ฌ ์•Œ๋ฆผ ์—ฌ๋ถ€๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค."), - FCM_TOKEN_CHANGE_ENABLE_STATE_FORBIDDEN(HttpStatus.FORBIDDEN, 200002, "ํ† ํฐ์„ ์†Œ์œ ํ•˜๊ณ  ์žˆ๋Š” ๊ณ„์ •์ด ์•„๋‹™๋‹ˆ๋‹ค."), + FCM_TOKEN_ACCESS_FORBIDDEN(HttpStatus.FORBIDDEN, 200002, "ํ† ํฐ์„ ์†Œ์œ ํ•˜๊ณ  ์žˆ๋Š” ๊ณ„์ •์ด ์•„๋‹™๋‹ˆ๋‹ค."), FIREBASE_SEND_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, 200003, "FCM ํ‘ธ์‰ฌ ์•Œ๋ฆผ ์ „์†ก์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.") ; diff --git a/src/main/java/konkuk/thip/common/swagger/SwaggerResponseDescription.java b/src/main/java/konkuk/thip/common/swagger/SwaggerResponseDescription.java index db2fc8e09..e22f9cf4c 100644 --- a/src/main/java/konkuk/thip/common/swagger/SwaggerResponseDescription.java +++ b/src/main/java/konkuk/thip/common/swagger/SwaggerResponseDescription.java @@ -337,8 +337,13 @@ public enum SwaggerResponseDescription { FCM_TOKEN_ENABLE_STATE_CHANGE(new LinkedHashSet<>(Set.of( USER_NOT_FOUND, FCM_TOKEN_NOT_FOUND, - FCM_TOKEN_ENABLED_STATE_ALREADY + FCM_TOKEN_ENABLED_STATE_ALREADY, + FCM_TOKEN_ACCESS_FORBIDDEN ))), + FCM_TOKEN_DELETE(new LinkedHashSet<>(Set.of( + FCM_TOKEN_NOT_FOUND, + FCM_TOKEN_ACCESS_FORBIDDEN + ))) ; private final Set errorCodeList; diff --git a/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java b/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java index c3d1d0ec8..3bab5cabd 100644 --- a/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java +++ b/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java @@ -6,6 +6,7 @@ import jakarta.validation.Valid; import konkuk.thip.common.dto.BaseResponse; import konkuk.thip.common.security.annotation.UserId; +import konkuk.thip.common.swagger.SwaggerResponseDescription; import konkuk.thip.common.swagger.annotation.ExceptionDescription; import konkuk.thip.notification.adapter.in.web.request.FcmTokenDeleteRequest; import konkuk.thip.notification.adapter.in.web.request.FcmTokenRegisterRequest; @@ -50,8 +51,9 @@ public BaseResponse updatePushNotificationSet FcmTokenEnableStateChangeResponse.of(fcmEnableStateChangeUseCase.changeEnableState(request.toCommand(userId)))); } - @DeleteMapping("/notifications/fcm-tokens") @Operation(summary = "FCM ํ† ํฐ ์‚ญ์ œ", description = "์‚ฌ์šฉ์ž์˜ FCM ํ† ํฐ์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.") + @ExceptionDescription(SwaggerResponseDescription) + @DeleteMapping("/notifications/fcm-tokens") public BaseResponse deleteFcmToken( @RequestBody @Valid FcmTokenDeleteRequest request, @Parameter(hidden = true) @UserId Long userId diff --git a/src/main/java/konkuk/thip/notification/application/service/FcmDeleteService.java b/src/main/java/konkuk/thip/notification/application/service/FcmDeleteService.java index 4a01f927f..d3258deb3 100644 --- a/src/main/java/konkuk/thip/notification/application/service/FcmDeleteService.java +++ b/src/main/java/konkuk/thip/notification/application/service/FcmDeleteService.java @@ -3,6 +3,7 @@ import konkuk.thip.notification.application.port.in.FcmDeleteUseCase; import konkuk.thip.notification.application.port.in.dto.FcmTokenDeleteCommand; import konkuk.thip.notification.application.port.out.FcmTokenLoadPort; +import konkuk.thip.notification.domain.FcmToken; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -13,10 +14,12 @@ public class FcmDeleteService implements FcmDeleteUseCase { private final FcmTokenLoadPort fcmTokenLoadPort; - @Override @Transactional public void deleteToken(FcmTokenDeleteCommand command) { + FcmToken fcmToken = fcmTokenLoadPort.getByDeviceIdOrThrow(command.deviceId()); + fcmToken.validateFcmOwner(command.userId()); + fcmTokenLoadPort.deleteByUserIdAndDeviceId(command.userId(), command.deviceId()); } } diff --git a/src/main/java/konkuk/thip/notification/domain/FcmToken.java b/src/main/java/konkuk/thip/notification/domain/FcmToken.java index 44a43bf8b..58bc299db 100644 --- a/src/main/java/konkuk/thip/notification/domain/FcmToken.java +++ b/src/main/java/konkuk/thip/notification/domain/FcmToken.java @@ -63,8 +63,12 @@ private void validateChangeEnableState(boolean enable, long actorUserId) { throw new InvalidStateException(ErrorCode.FCM_TOKEN_ENABLED_STATE_ALREADY, new IllegalArgumentException("์ด๋ฏธ " + (enable ? "ํ™œ์„ฑํ™”" : "๋น„ํ™œ์„ฑํ™”") + "๋œ ์ƒํƒœ์ž…๋‹ˆ๋‹ค.")); } + validateFcmOwner(actorUserId); + } + + public void validateFcmOwner(long actorUserId) { if (this.userId != actorUserId) { - throw new InvalidStateException(ErrorCode.FCM_TOKEN_CHANGE_ENABLE_STATE_FORBIDDEN); + throw new InvalidStateException(ErrorCode.FCM_TOKEN_ACCESS_FORBIDDEN); } } } From 20349e2a89082f112318aac2aed2efcf76deb6f6 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 14:41:14 +0900 Subject: [PATCH 74/93] =?UTF-8?q?[docs]=20=ED=86=A0=ED=81=B0=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20api=20=EC=8A=A4=EC=9B=A8=EA=B1=B0=20=EB=AA=85?= =?UTF-8?q?=EC=84=B8=20=EC=B6=94=EA=B0=80=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/in/web/NotificationCommandController.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java b/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java index 3bab5cabd..b6d3772f5 100644 --- a/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java +++ b/src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java @@ -6,15 +6,14 @@ import jakarta.validation.Valid; import konkuk.thip.common.dto.BaseResponse; import konkuk.thip.common.security.annotation.UserId; -import konkuk.thip.common.swagger.SwaggerResponseDescription; import konkuk.thip.common.swagger.annotation.ExceptionDescription; import konkuk.thip.notification.adapter.in.web.request.FcmTokenDeleteRequest; +import konkuk.thip.notification.adapter.in.web.request.FcmTokenEnableStateChangeRequest; import konkuk.thip.notification.adapter.in.web.request.FcmTokenRegisterRequest; import konkuk.thip.notification.adapter.in.web.response.FcmTokenEnableStateChangeResponse; +import konkuk.thip.notification.application.port.in.FcmDeleteUseCase; import konkuk.thip.notification.application.port.in.FcmEnableStateChangeUseCase; import konkuk.thip.notification.application.port.in.FcmRegisterUseCase; -import konkuk.thip.notification.adapter.in.web.request.FcmTokenEnableStateChangeRequest; -import konkuk.thip.notification.application.port.in.FcmDeleteUseCase; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; @@ -52,7 +51,7 @@ public BaseResponse updatePushNotificationSet } @Operation(summary = "FCM ํ† ํฐ ์‚ญ์ œ", description = "์‚ฌ์šฉ์ž์˜ FCM ํ† ํฐ์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.") - @ExceptionDescription(SwaggerResponseDescription) + @ExceptionDescription(FCM_TOKEN_DELETE) @DeleteMapping("/notifications/fcm-tokens") public BaseResponse deleteFcmToken( @RequestBody @Valid FcmTokenDeleteRequest request, From 24e001ad70a9680cb6a2f8b7e70b7ac55e5e7162 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 15:06:47 +0900 Subject: [PATCH 75/93] =?UTF-8?q?[refactor]=20thread=20=EC=84=A4=EC=A0=95?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=ED=99=98=EA=B2=BD=EC=97=90?= =?UTF-8?q?=EC=84=9C=EB=8A=94=20=EB=8F=99=EA=B8=B0=EC=A0=81=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/config/WorkerThreadConfig.java | 2 ++ .../konkuk/thip/config/TestAsyncConfig.java | 22 ++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/main/java/konkuk/thip/config/WorkerThreadConfig.java b/src/main/java/konkuk/thip/config/WorkerThreadConfig.java index 88517f8f0..f8dceaafd 100644 --- a/src/main/java/konkuk/thip/config/WorkerThreadConfig.java +++ b/src/main/java/konkuk/thip/config/WorkerThreadConfig.java @@ -4,6 +4,7 @@ import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; import org.springframework.scheduling.annotation.AsyncConfigurer; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; @@ -12,6 +13,7 @@ @Configuration @EnableAsync +@Profile("!test") public class WorkerThreadConfig implements AsyncConfigurer { /** diff --git a/src/test/java/konkuk/thip/config/TestAsyncConfig.java b/src/test/java/konkuk/thip/config/TestAsyncConfig.java index 398f62fb9..76bcb276f 100644 --- a/src/test/java/konkuk/thip/config/TestAsyncConfig.java +++ b/src/test/java/konkuk/thip/config/TestAsyncConfig.java @@ -4,15 +4,27 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.core.task.SyncTaskExecutor; +import org.springframework.scheduling.annotation.AsyncConfigurer; import java.util.concurrent.Executor; +// ํ…Œ์ŠคํŠธ์šฉ: ๋™๊ธฐ ์‹คํ–‰ ๊ฐ•์ œ @Configuration @Profile("test") -public class TestAsyncConfig { - @Bean(name = "taskExecutor") - public Executor taskExecutor() { - return new SyncTaskExecutor(); // ๋™๊ธฐ ์‹คํ–‰ +public class TestAsyncConfig implements AsyncConfigurer { + + @Bean(name = "fcmAsyncExecutor") + public Executor fcmAsyncExecutor() { + return new SyncTaskExecutor(); + } + + @Bean(name = "schedulerAsyncExecutor") + public Executor schedulerAsyncExecutor() { + return new SyncTaskExecutor(); } -} + @Override + public Executor getAsyncExecutor() { + return new SyncTaskExecutor(); + } +} \ No newline at end of file From 4a3a1ce8ceb8a151101a9def6ba5a5bd87e5937d Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 15:15:24 +0900 Subject: [PATCH 76/93] =?UTF-8?q?[refactor]=20=EB=B0=95=EC=8B=B1=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EC=82=AC=EC=9A=A9=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../in/web/request/FcmTokenEnableStateChangeRequest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenEnableStateChangeRequest.java b/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenEnableStateChangeRequest.java index d6d77bcb8..767032e35 100644 --- a/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenEnableStateChangeRequest.java +++ b/src/main/java/konkuk/thip/notification/adapter/in/web/request/FcmTokenEnableStateChangeRequest.java @@ -9,7 +9,7 @@ public record FcmTokenEnableStateChangeRequest( @NotNull @Schema(description = "ํ‘ธ์‹œ ์•Œ๋ฆผ ์ˆ˜์‹  ์—ฌ๋ถ€", example = "true") - boolean enable, + Boolean enable, @NotBlank @Schema(description = "๋””๋ฐ”์ด์Šค ๊ณ ์œ  ID", example = "device12345") From bdf108e040fd7803a3790702b641af2ea74a6217 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 15:18:08 +0900 Subject: [PATCH 77/93] =?UTF-8?q?[refactor]=20=EB=B9=84=EB=8F=99=EA=B8=B0?= =?UTF-8?q?=20=EB=B0=B1=EC=97=85=20=EC=A0=84=EB=9E=B5=20=EC=A0=81=EC=9A=A9?= =?UTF-8?q?=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/konkuk/thip/config/WorkerThreadConfig.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/konkuk/thip/config/WorkerThreadConfig.java b/src/main/java/konkuk/thip/config/WorkerThreadConfig.java index f8dceaafd..0f32626ef 100644 --- a/src/main/java/konkuk/thip/config/WorkerThreadConfig.java +++ b/src/main/java/konkuk/thip/config/WorkerThreadConfig.java @@ -10,6 +10,7 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; @Configuration @EnableAsync @@ -47,7 +48,8 @@ public Executor schedulerAsyncExecutor() { executor.setQueueCapacity(10); // ์ž‘์€ ํ (์Šค์ผ€์ค„๋ง๋œ ์ž‘์—…์ด๋ฏ€๋กœ) executor.setThreadNamePrefix("scheduler-"); executor.setWaitForTasksToCompleteOnShutdown(true); -// executor.setAwaitTerminationSeconds(120); // ๋ฐฐ์น˜์ž‘์—… ์™„๋ฃŒ ๋Œ€๊ธฐ์‹œ๊ฐ„ + executor.setAwaitTerminationSeconds(120); // ๋ฐฐ์น˜์ž‘์—… ์™„๋ฃŒ ๋Œ€๊ธฐ์‹œ๊ฐ„ + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; } From fddf09f7e01e246eab676cb5600ada6e1b9cb259 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 15:22:10 +0900 Subject: [PATCH 78/93] =?UTF-8?q?[refactor]=20=EB=B3=B8=EC=9D=B8=EC=9D=B4?= =?UTF-8?q?=20=EC=9E=91=EC=84=B1=ED=95=9C=20=EA=B2=8C=EC=8B=9C=EA=B8=80?= =?UTF-8?q?=EC=9D=98=20=EB=8C=93=EA=B8=80,=20=EB=8C=93=EA=B8=80=EC=9D=98?= =?UTF-8?q?=20=EB=8B=B5=EA=B8=80=EC=97=90=20=EB=8C=80=ED=95=9C=20=ED=91=B8?= =?UTF-8?q?=EC=89=AC=EC=95=8C=EB=A6=BC=20=EC=A0=9C=EC=99=B8=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/application/service/CommentCreateService.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/konkuk/thip/comment/application/service/CommentCreateService.java b/src/main/java/konkuk/thip/comment/application/service/CommentCreateService.java index 57b808ce2..b959bbfb9 100644 --- a/src/main/java/konkuk/thip/comment/application/service/CommentCreateService.java +++ b/src/main/java/konkuk/thip/comment/application/service/CommentCreateService.java @@ -92,6 +92,8 @@ public CommentCreateResponse createComment(CommentCreateCommand command) { } private void sendNotificationsToPostWriter(PostQueryDto postQueryDto, User actorUser) { + if (postQueryDto.creatorId().equals(actorUser.getId())) return; // ์ž์‹ ์ด ์ž‘์„ฑํ•œ ๊ฒŒ์‹œ๊ธ€ ์ œ์™ธ + if (postQueryDto.postType().equals(FEED.getType())) { // ํ”ผ๋“œ ๋Œ“๊ธ€ ์•Œ๋ฆผ ์ด๋ฒคํŠธ ๋ฐœํ–‰ feedEventCommandPort.publishFeedCommentedEvent(postQueryDto.creatorId(), actorUser.getId(), actorUser.getNickname(), postQueryDto.postId()); @@ -102,6 +104,8 @@ private void sendNotificationsToPostWriter(PostQueryDto postQueryDto, User actor } private void sendNotificationsToParentCommentWriter(PostQueryDto postQueryDto, CommentQueryDto parentCommentDto, User actorUser) { + if (parentCommentDto.creatorId().equals(actorUser.getId())) return; // ์ž์‹ ์ด ์ž‘์„ฑํ•œ ๋Œ“๊ธ€ ์ œ์™ธ + if (postQueryDto.postType().equals(FEED.getType())) { // ํ”ผ๋“œ ๋‹ต๊ธ€ ์•Œ๋ฆผ ์ด๋ฒคํŠธ ๋ฐœํ–‰ feedEventCommandPort.publishFeedRepliedEvent(parentCommentDto.creatorId(), actorUser.getId(), actorUser.getNickname(), postQueryDto.postId()); From fb41ab3d9e24f4c911da4d0d63327c5eff177a25 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 15:23:53 +0900 Subject: [PATCH 79/93] =?UTF-8?q?[refactor]=20=EC=B1=85=20=EB=9E=AD?= =?UTF-8?q?=ED=82=B9=20=EC=84=A4=EC=A0=95=20=EC=8A=A4=EC=BC=80=EC=A4=84?= =?UTF-8?q?=EB=9F=AC=EB=8F=84=20ThreadPoolExececutor=20=EB=AA=85=EC=8B=9C?= =?UTF-8?q?=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../book/application/service/BookMostSearchRankService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/konkuk/thip/book/application/service/BookMostSearchRankService.java b/src/main/java/konkuk/thip/book/application/service/BookMostSearchRankService.java index 9711da9bf..50d90c1a5 100644 --- a/src/main/java/konkuk/thip/book/application/service/BookMostSearchRankService.java +++ b/src/main/java/konkuk/thip/book/application/service/BookMostSearchRankService.java @@ -28,7 +28,7 @@ public class BookMostSearchRankService { private final BookCommandPort bookCommandPort; // ๋งค์ผ 0์‹œ ์‹คํ–‰ - @Async + @Async("schedulerAsyncExecutor") @Scheduled(cron = "0 0 0 * * *") public void updateDailySearchRank() { From e012be411fecc6e201006420ab7564764979aeb6 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Fri, 5 Sep 2025 15:25:30 +0900 Subject: [PATCH 80/93] =?UTF-8?q?[refactor]=20TestAsyncConfig=EC=97=90=20E?= =?UTF-8?q?nableAsync=20=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EB=AA=85=EC=8B=9C=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/konkuk/thip/config/TestAsyncConfig.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/konkuk/thip/config/TestAsyncConfig.java b/src/test/java/konkuk/thip/config/TestAsyncConfig.java index 76bcb276f..e6b2d97cd 100644 --- a/src/test/java/konkuk/thip/config/TestAsyncConfig.java +++ b/src/test/java/konkuk/thip/config/TestAsyncConfig.java @@ -5,10 +5,12 @@ import org.springframework.context.annotation.Profile; import org.springframework.core.task.SyncTaskExecutor; import org.springframework.scheduling.annotation.AsyncConfigurer; +import org.springframework.scheduling.annotation.EnableAsync; import java.util.concurrent.Executor; // ํ…Œ์ŠคํŠธ์šฉ: ๋™๊ธฐ ์‹คํ–‰ ๊ฐ•์ œ +@EnableAsync @Configuration @Profile("test") public class TestAsyncConfig implements AsyncConfigurer { From b048c8c11e8d9ed2ec3c84b02131b4720085afd7 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Sun, 7 Sep 2025 00:29:25 +0900 Subject: [PATCH 81/93] =?UTF-8?q?[refactor]=20ManyToOne=20option=EC=97=90?= =?UTF-8?q?=20optional=20=3D=20false=20=EC=B6=94=EA=B0=80=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../thip/notification/adapter/out/jpa/FcmTokenJpaEntity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/konkuk/thip/notification/adapter/out/jpa/FcmTokenJpaEntity.java b/src/main/java/konkuk/thip/notification/adapter/out/jpa/FcmTokenJpaEntity.java index ec2070d34..25ea5fc29 100644 --- a/src/main/java/konkuk/thip/notification/adapter/out/jpa/FcmTokenJpaEntity.java +++ b/src/main/java/konkuk/thip/notification/adapter/out/jpa/FcmTokenJpaEntity.java @@ -37,7 +37,7 @@ public class FcmTokenJpaEntity extends BaseJpaEntity { @Column(name = "is_enabled", nullable = false) private boolean isEnabled; // ํ‘ธ์‰ฌ์•Œ๋ฆผ ์ˆ˜์‹  ์—ฌ๋ถ€ - @ManyToOne(fetch = FetchType.LAZY) + @ManyToOne(fetch = FetchType.LAZY, optional = false) @JoinColumn(name = "user_id", nullable = false) private UserJpaEntity userJpaEntity; From 6fec14274c0ca9d85d67946d5066425f5e5ba1ca Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Sun, 7 Sep 2025 00:29:43 +0900 Subject: [PATCH 82/93] =?UTF-8?q?[refactor]=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EC=8B=9C=EA=B7=B8=EB=8B=88=EC=B2=98=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=95=A0=EB=A7=A4=ED=95=9C=20=ED=8C=8C=EB=9D=BC=EB=AF=B8?= =?UTF-8?q?=ED=84=B0=20=EC=82=AD=EC=A0=9C=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../out/persistence/RoomCommandPersistenceAdapter.java | 4 ++-- .../thip/room/application/port/out/RoomCommandPort.java | 2 +- .../thip/room/application/service/RoomStateChangeService.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomCommandPersistenceAdapter.java b/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomCommandPersistenceAdapter.java index c1bac561f..f859b50ab 100644 --- a/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomCommandPersistenceAdapter.java +++ b/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomCommandPersistenceAdapter.java @@ -65,8 +65,8 @@ public int updateRoomStateToExpired(RoomStatus exceptStatus) { } @Override - public int updateRoomStateToInProgress(RoomStatus fromStatus, RoomStatus toStatus) { - return roomJpaRepository.updateRoomStatusToInProgress(fromStatus, toStatus); + public int updateRoomState(RoomStatus fromStatus, RoomStatus toStatus) { + return roomJpaRepository.updateRoomStatus(fromStatus, toStatus); } @Override diff --git a/src/main/java/konkuk/thip/room/application/port/out/RoomCommandPort.java b/src/main/java/konkuk/thip/room/application/port/out/RoomCommandPort.java index e965c7b77..4b18dd2b9 100644 --- a/src/main/java/konkuk/thip/room/application/port/out/RoomCommandPort.java +++ b/src/main/java/konkuk/thip/room/application/port/out/RoomCommandPort.java @@ -24,7 +24,7 @@ default Room getByIdOrThrow(Long id) { int updateRoomStateToExpired(RoomStatus exceptStatus); - int updateRoomStateToInProgress(RoomStatus fromStatus, RoomStatus toStatus); + int updateRoomState(RoomStatus fromStatus, RoomStatus toStatus); List findProgressTargetRooms(RoomStatus status); } diff --git a/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java b/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java index b1e46a151..a073304ae 100644 --- a/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java +++ b/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java @@ -46,7 +46,7 @@ public void changeRoomStateToProgress() { // ๋ฐฉ ๋ชจ์ž„๋ฐฉ ํ™œ๋™ ์‹œ์ž‘ ํ‘ธ์‰ฌ์•Œ๋ฆผ ์ „์†ก sendNotifications(); - int updated = roomCommandPort.updateRoomStateToInProgress(RoomStatus.RECRUITING, RoomStatus.IN_PROGRESS); + int updated = roomCommandPort.updateRoomState(RoomStatus.RECRUITING, RoomStatus.IN_PROGRESS); log.info("[RoomState] IN_PROGRESS๋กœ ๋ณ€๊ฒฝ๋œ ๊ฑด์ˆ˜={}", updated); } From ffa5810d4cfd09221a7d721e228fc72f6b2b94ba Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Sun, 7 Sep 2025 00:29:53 +0900 Subject: [PATCH 83/93] =?UTF-8?q?[fix]=20param=20=EB=B0=94=EC=9D=B8?= =?UTF-8?q?=EB=94=A9=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/out/persistence/repository/RoomJpaRepository.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/RoomJpaRepository.java b/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/RoomJpaRepository.java index 248e9273c..a606f9681 100644 --- a/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/RoomJpaRepository.java +++ b/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/RoomJpaRepository.java @@ -30,7 +30,7 @@ public interface RoomJpaRepository extends JpaRepository, R @Modifying(clearAutomatically = true, flushAutomatically = true) @Query(""" update RoomJpaEntity r - set r.roomStatus = :status + set r.roomStatus = :exceptStatus where r.endDate < current_date and r.roomStatus <> :exceptStatus """) @@ -48,7 +48,7 @@ public interface RoomJpaRepository extends JpaRepository, R and r.endDate >= current_date and r.roomStatus = :fromStatus """) - int updateRoomStatusToInProgress(@Param("fromStatus") RoomStatus fromStatus, @Param("toStatus") RoomStatus toStatus); + int updateRoomStatus(@Param("fromStatus") RoomStatus fromStatus, @Param("toStatus") RoomStatus toStatus); @Query(""" select r From 9ad3d9ab788b77191392028de7c823c5ccd66219 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Sun, 7 Sep 2025 00:31:43 +0900 Subject: [PATCH 84/93] =?UTF-8?q?[refactor]=20Fcm=20=EC=98=81=EC=86=8D?= =?UTF-8?q?=EC=84=B1=20port=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/FeedNotificationDispatchService.java | 8 ++++---- .../service/RoomNotificationDispatchService.java | 4 ++-- ...java => FcmTokenPersistencePersistenceAdapter.java} | 4 ++-- ...TokenLoadPort.java => FcmTokenPersistencePort.java} | 2 +- .../application/service/FcmDeleteService.java | 8 ++++---- .../service/FcmEnableStateChangeService.java | 8 ++++---- .../application/service/FcmRegisterService.java | 10 +++++----- 7 files changed, 22 insertions(+), 22 deletions(-) rename src/main/java/konkuk/thip/notification/adapter/out/persistence/{FcmTokenLoadPersistenceAdapter.java => FcmTokenPersistencePersistenceAdapter.java} (93%) rename src/main/java/konkuk/thip/notification/application/port/out/{FcmTokenLoadPort.java => FcmTokenPersistencePort.java} (94%) diff --git a/src/main/java/konkuk/thip/message/application/service/FeedNotificationDispatchService.java b/src/main/java/konkuk/thip/message/application/service/FeedNotificationDispatchService.java index 2ae8c9ad1..27ecdcd7b 100644 --- a/src/main/java/konkuk/thip/message/application/service/FeedNotificationDispatchService.java +++ b/src/main/java/konkuk/thip/message/application/service/FeedNotificationDispatchService.java @@ -7,7 +7,7 @@ import konkuk.thip.message.adapter.out.event.dto.FeedEvents; import konkuk.thip.message.domain.NotificationCategory; import konkuk.thip.message.domain.MessageRoute; -import konkuk.thip.notification.application.port.out.FcmTokenLoadPort; +import konkuk.thip.notification.application.port.out.FcmTokenPersistencePort; import konkuk.thip.notification.domain.FcmToken; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -21,7 +21,7 @@ @Transactional(readOnly = true) public class FeedNotificationDispatchService implements FeedNotificationDispatchUseCase { - private final FcmTokenLoadPort fcmTokenLoadPort; + private final FcmTokenPersistencePort fcmTokenPersistencePort; private final FirebaseMessagingPort firebasePort; @Override @@ -29,7 +29,7 @@ public void handleFollower(final FeedEvents.FollowerEvent event) { Notification n = buildNotification("ํŒ”๋กœ์›Œ ์•Œ๋ฆผ", "@" + event.actorUsername() + " ๋‹˜์ด ๋‚˜๋ฅผ ๋ฑํ–ˆ์–ด์š”!"); - List tokens = fcmTokenLoadPort.findEnabledByUserId(event.targetUserId()); + List tokens = fcmTokenPersistencePort.findEnabledByUserId(event.targetUserId()); if (tokens.isEmpty()) return; @@ -88,7 +88,7 @@ public void handleFeedCommentLiked(final FeedEvents.FeedCommentLikedEvent event) } private void pushFeedDetail(Long userId, Notification notification, Long feedId) { - List tokens = fcmTokenLoadPort.findEnabledByUserId(userId); + List tokens = fcmTokenPersistencePort.findEnabledByUserId(userId); if (tokens.isEmpty()) return; diff --git a/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java b/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java index 83bb127ee..93acf0b81 100644 --- a/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java +++ b/src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java @@ -7,7 +7,7 @@ import konkuk.thip.message.adapter.out.event.dto.RoomEvents; import konkuk.thip.message.domain.NotificationCategory; import konkuk.thip.message.domain.MessageRoute; -import konkuk.thip.notification.application.port.out.FcmTokenLoadPort; +import konkuk.thip.notification.application.port.out.FcmTokenPersistencePort; import konkuk.thip.notification.domain.FcmToken; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -21,7 +21,7 @@ @Transactional(readOnly = true) public class RoomNotificationDispatchService implements RoomNotificationDispatchUseCase { - private final FcmTokenLoadPort fcmTokenQueryPort; + private final FcmTokenPersistencePort fcmTokenQueryPort; private final FirebaseMessagingPort firebasePort; @Override diff --git a/src/main/java/konkuk/thip/notification/adapter/out/persistence/FcmTokenLoadPersistenceAdapter.java b/src/main/java/konkuk/thip/notification/adapter/out/persistence/FcmTokenPersistencePersistenceAdapter.java similarity index 93% rename from src/main/java/konkuk/thip/notification/adapter/out/persistence/FcmTokenLoadPersistenceAdapter.java rename to src/main/java/konkuk/thip/notification/adapter/out/persistence/FcmTokenPersistencePersistenceAdapter.java index 8a4275755..8c30fd173 100644 --- a/src/main/java/konkuk/thip/notification/adapter/out/persistence/FcmTokenLoadPersistenceAdapter.java +++ b/src/main/java/konkuk/thip/notification/adapter/out/persistence/FcmTokenPersistencePersistenceAdapter.java @@ -5,7 +5,7 @@ import konkuk.thip.notification.adapter.out.jpa.FcmTokenJpaEntity; import konkuk.thip.notification.adapter.out.mapper.FcmTokenMapper; import konkuk.thip.notification.adapter.out.persistence.repository.FcmTokenJpaRepository; -import konkuk.thip.notification.application.port.out.FcmTokenLoadPort; +import konkuk.thip.notification.application.port.out.FcmTokenPersistencePort; import konkuk.thip.notification.domain.FcmToken; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; @@ -17,7 +17,7 @@ @Repository @RequiredArgsConstructor -public class FcmTokenLoadPersistenceAdapter implements FcmTokenLoadPort { +public class FcmTokenPersistencePersistenceAdapter implements FcmTokenPersistencePort { private final FcmTokenJpaRepository fcmTokenJpaRepository; private final UserJpaRepository userJpaRepository; diff --git a/src/main/java/konkuk/thip/notification/application/port/out/FcmTokenLoadPort.java b/src/main/java/konkuk/thip/notification/application/port/out/FcmTokenPersistencePort.java similarity index 94% rename from src/main/java/konkuk/thip/notification/application/port/out/FcmTokenLoadPort.java rename to src/main/java/konkuk/thip/notification/application/port/out/FcmTokenPersistencePort.java index 388623c6c..0c4523685 100644 --- a/src/main/java/konkuk/thip/notification/application/port/out/FcmTokenLoadPort.java +++ b/src/main/java/konkuk/thip/notification/application/port/out/FcmTokenPersistencePort.java @@ -7,7 +7,7 @@ import java.util.List; import java.util.Optional; -public interface FcmTokenLoadPort { +public interface FcmTokenPersistencePort { Optional findByDeviceId(String deviceId); default FcmToken getByDeviceIdOrThrow(String deviceId) { diff --git a/src/main/java/konkuk/thip/notification/application/service/FcmDeleteService.java b/src/main/java/konkuk/thip/notification/application/service/FcmDeleteService.java index d3258deb3..b08f5ab45 100644 --- a/src/main/java/konkuk/thip/notification/application/service/FcmDeleteService.java +++ b/src/main/java/konkuk/thip/notification/application/service/FcmDeleteService.java @@ -2,7 +2,7 @@ import konkuk.thip.notification.application.port.in.FcmDeleteUseCase; import konkuk.thip.notification.application.port.in.dto.FcmTokenDeleteCommand; -import konkuk.thip.notification.application.port.out.FcmTokenLoadPort; +import konkuk.thip.notification.application.port.out.FcmTokenPersistencePort; import konkuk.thip.notification.domain.FcmToken; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -12,14 +12,14 @@ @RequiredArgsConstructor public class FcmDeleteService implements FcmDeleteUseCase { - private final FcmTokenLoadPort fcmTokenLoadPort; + private final FcmTokenPersistencePort fcmTokenPersistencePort; @Override @Transactional public void deleteToken(FcmTokenDeleteCommand command) { - FcmToken fcmToken = fcmTokenLoadPort.getByDeviceIdOrThrow(command.deviceId()); + FcmToken fcmToken = fcmTokenPersistencePort.getByDeviceIdOrThrow(command.deviceId()); fcmToken.validateFcmOwner(command.userId()); - fcmTokenLoadPort.deleteByUserIdAndDeviceId(command.userId(), command.deviceId()); + fcmTokenPersistencePort.deleteByUserIdAndDeviceId(command.userId(), command.deviceId()); } } diff --git a/src/main/java/konkuk/thip/notification/application/service/FcmEnableStateChangeService.java b/src/main/java/konkuk/thip/notification/application/service/FcmEnableStateChangeService.java index 36c52a82e..abae5af41 100644 --- a/src/main/java/konkuk/thip/notification/application/service/FcmEnableStateChangeService.java +++ b/src/main/java/konkuk/thip/notification/application/service/FcmEnableStateChangeService.java @@ -2,7 +2,7 @@ import konkuk.thip.notification.application.port.in.FcmEnableStateChangeUseCase; import konkuk.thip.notification.application.port.in.dto.FcmEnableStateChangeCommand; -import konkuk.thip.notification.application.port.out.FcmTokenLoadPort; +import konkuk.thip.notification.application.port.out.FcmTokenPersistencePort; import konkuk.thip.notification.domain.FcmToken; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -12,15 +12,15 @@ @RequiredArgsConstructor public class FcmEnableStateChangeService implements FcmEnableStateChangeUseCase { - private final FcmTokenLoadPort fcmTokenLoadPort; + private final FcmTokenPersistencePort fcmTokenPersistencePort; @Override @Transactional public boolean changeEnableState(FcmEnableStateChangeCommand command) { - FcmToken fcmToken = fcmTokenLoadPort.getByDeviceIdOrThrow(command.deviceId()); + FcmToken fcmToken = fcmTokenPersistencePort.getByDeviceIdOrThrow(command.deviceId()); fcmToken.changeEnableState(command.enable(), command.userId()); - fcmTokenLoadPort.update(fcmToken); + fcmTokenPersistencePort.update(fcmToken); return command.enable(); } diff --git a/src/main/java/konkuk/thip/notification/application/service/FcmRegisterService.java b/src/main/java/konkuk/thip/notification/application/service/FcmRegisterService.java index f64dd14b7..71f8835d2 100644 --- a/src/main/java/konkuk/thip/notification/application/service/FcmRegisterService.java +++ b/src/main/java/konkuk/thip/notification/application/service/FcmRegisterService.java @@ -2,7 +2,7 @@ import konkuk.thip.notification.application.port.in.FcmRegisterUseCase; import konkuk.thip.notification.application.port.in.dto.FcmTokenRegisterCommand; -import konkuk.thip.notification.application.port.out.FcmTokenLoadPort; +import konkuk.thip.notification.application.port.out.FcmTokenPersistencePort; import konkuk.thip.notification.domain.FcmToken; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -14,13 +14,13 @@ @RequiredArgsConstructor public class FcmRegisterService implements FcmRegisterUseCase { - private final FcmTokenLoadPort fcmTokenLoadPort; + private final FcmTokenPersistencePort fcmTokenPersistencePort; @Override @Transactional public void registerToken(FcmTokenRegisterCommand command) { // ๊ฐ™์€ ๋””๋ฐ”์ด์Šค๋กœ ๋“ฑ๋ก๋œ ํ† ํฐ์ด ์žˆ๋Š”์ง€ ํ™•์ธ - fcmTokenLoadPort.findByDeviceId(command.deviceId()).ifPresentOrElse( + fcmTokenPersistencePort.findByDeviceId(command.deviceId()).ifPresentOrElse( existingToken -> { // ์žˆ์œผ๋ฉด ์ƒˆ๋กœ์šด ๊ณ„์ •์œผ๋กœ ๊ต์ฒด ๋˜๋Š” ๊ธฐ์กด ๊ณ„์ •์˜ ํ† ํฐ ๊ฐฑ์‹  existingToken.updateToken( @@ -29,11 +29,11 @@ public void registerToken(FcmTokenRegisterCommand command) { LocalDate.now(), command.userId() ); - fcmTokenLoadPort.update(existingToken); + fcmTokenPersistencePort.update(existingToken); }, () -> { // ์—†์œผ๋ฉด ์ƒˆ๋กœ ๋“ฑ๋ก - fcmTokenLoadPort.save(FcmToken.withoutId( + fcmTokenPersistencePort.save(FcmToken.withoutId( command.fcmToken(), command.deviceId(), command.platformType(), From a24e11e03e75bee6e2a767e85d3feaf71ee4b4cc Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Sun, 7 Sep 2025 11:40:48 +0900 Subject: [PATCH 85/93] =?UTF-8?q?[refactor]=20=EC=BF=BC=EB=A6=AC=20?= =?UTF-8?q?=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EC=88=98=EC=A0=95=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RoomCommandPersistenceAdapter.java | 16 ++++++++-------- .../repository/RoomJpaRepository.java | 17 ++++++++--------- .../application/port/out/RoomCommandPort.java | 7 +++---- .../service/RoomStateChangeService.java | 7 +++---- 4 files changed, 22 insertions(+), 25 deletions(-) diff --git a/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomCommandPersistenceAdapter.java b/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomCommandPersistenceAdapter.java index f859b50ab..76c0053d7 100644 --- a/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomCommandPersistenceAdapter.java +++ b/src/main/java/konkuk/thip/room/adapter/out/persistence/RoomCommandPersistenceAdapter.java @@ -4,7 +4,6 @@ import konkuk.thip.book.adapter.out.persistence.repository.BookJpaRepository; import konkuk.thip.common.exception.EntityNotFoundException; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.domain.value.RoomStatus; import konkuk.thip.room.adapter.out.mapper.RoomMapper; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.application.port.out.RoomCommandPort; @@ -15,7 +14,8 @@ import java.util.List; import java.util.Optional; -import static konkuk.thip.common.exception.code.ErrorCode.*; +import static konkuk.thip.common.exception.code.ErrorCode.BOOK_NOT_FOUND; +import static konkuk.thip.common.exception.code.ErrorCode.ROOM_NOT_FOUND; @Repository @RequiredArgsConstructor @@ -60,18 +60,18 @@ public void update(Room room) { } @Override - public int updateRoomStateToExpired(RoomStatus exceptStatus) { - return roomJpaRepository.updateRoomStatusToExpired(exceptStatus); + public int updateRoomStateToExpired() { + return roomJpaRepository.updateRoomStatusToExpired(); } @Override - public int updateRoomState(RoomStatus fromStatus, RoomStatus toStatus) { - return roomJpaRepository.updateRoomStatus(fromStatus, toStatus); + public int updateRoomStateFromRecruitingToProgress() { + return roomJpaRepository.updateRoomStatusFromRecruitingToProgress(); } @Override - public List findProgressTargetRooms(RoomStatus status) { - List roomJpaEntities = roomJpaRepository.findProgressTargetIds(status); + public List findProgressTargetRooms() { + List roomJpaEntities = roomJpaRepository.findProgressTargetIds(); return roomJpaEntities.stream() .map(roomMapper::toDomainEntity) .toList(); diff --git a/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/RoomJpaRepository.java b/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/RoomJpaRepository.java index a606f9681..5ac595033 100644 --- a/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/RoomJpaRepository.java +++ b/src/main/java/konkuk/thip/room/adapter/out/persistence/repository/RoomJpaRepository.java @@ -1,7 +1,6 @@ package konkuk.thip.room.adapter.out.persistence.repository; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.domain.value.RoomStatus; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; @@ -30,11 +29,11 @@ public interface RoomJpaRepository extends JpaRepository, R @Modifying(clearAutomatically = true, flushAutomatically = true) @Query(""" update RoomJpaEntity r - set r.roomStatus = :exceptStatus + set r.roomStatus = 'EXPIRED' where r.endDate < current_date - and r.roomStatus <> :exceptStatus + and r.roomStatus <> 'EXPIRED' """) - int updateRoomStatusToExpired(@Param("exceptStatus") RoomStatus exceptStatus); + int updateRoomStatusToExpired(); /** * start_date <= ์˜ค๋Š˜ AND end_date >= ์˜ค๋Š˜ => IN_PROGRESS @@ -43,19 +42,19 @@ public interface RoomJpaRepository extends JpaRepository, R @Modifying(clearAutomatically = true, flushAutomatically = true) @Query(""" update RoomJpaEntity r - set r.roomStatus = :toStatus + set r.roomStatus = 'IN_PROGRESS' where r.startDate <= current_date and r.endDate >= current_date - and r.roomStatus = :fromStatus + and r.roomStatus = 'RECRUITING' """) - int updateRoomStatus(@Param("fromStatus") RoomStatus fromStatus, @Param("toStatus") RoomStatus toStatus); + int updateRoomStatusFromRecruitingToProgress(); @Query(""" select r from RoomJpaEntity r where r.startDate <= current_date and r.endDate >= current_date - and r.roomStatus = :status + and r.roomStatus = 'RECRUITING' """) - List findProgressTargetIds(@Param("status") RoomStatus status); + List findProgressTargetIds(); } diff --git a/src/main/java/konkuk/thip/room/application/port/out/RoomCommandPort.java b/src/main/java/konkuk/thip/room/application/port/out/RoomCommandPort.java index 4b18dd2b9..cfa305590 100644 --- a/src/main/java/konkuk/thip/room/application/port/out/RoomCommandPort.java +++ b/src/main/java/konkuk/thip/room/application/port/out/RoomCommandPort.java @@ -1,7 +1,6 @@ package konkuk.thip.room.application.port.out; import konkuk.thip.common.exception.EntityNotFoundException; -import konkuk.thip.room.domain.value.RoomStatus; import konkuk.thip.room.domain.Room; import java.util.List; @@ -22,9 +21,9 @@ default Room getByIdOrThrow(Long id) { void update(Room room); - int updateRoomStateToExpired(RoomStatus exceptStatus); + int updateRoomStateToExpired(); - int updateRoomState(RoomStatus fromStatus, RoomStatus toStatus); + int updateRoomStateFromRecruitingToProgress(); - List findProgressTargetRooms(RoomStatus status); + List findProgressTargetRooms(); } diff --git a/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java b/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java index a073304ae..7bb9604ff 100644 --- a/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java +++ b/src/main/java/konkuk/thip/room/application/service/RoomStateChangeService.java @@ -1,7 +1,6 @@ package konkuk.thip.room.application.service; import konkuk.thip.message.application.port.out.RoomEventCommandPort; -import konkuk.thip.room.domain.value.RoomStatus; import konkuk.thip.room.application.port.in.RoomStateChangeUseCase; import konkuk.thip.room.application.port.out.RoomCommandPort; import konkuk.thip.room.application.port.out.RoomParticipantCommandPort; @@ -32,7 +31,7 @@ public class RoomStateChangeService implements RoomStateChangeUseCase { @Override @Transactional public void changeRoomStateToExpired() { - int updated = roomCommandPort.updateRoomStateToExpired(RoomStatus.EXPIRED); + int updated = roomCommandPort.updateRoomStateToExpired(); log.info("[RoomState] EXPIRED๋กœ ๋ณ€๊ฒฝ๋œ ๊ฑด์ˆ˜={}", updated); } @@ -46,12 +45,12 @@ public void changeRoomStateToProgress() { // ๋ฐฉ ๋ชจ์ž„๋ฐฉ ํ™œ๋™ ์‹œ์ž‘ ํ‘ธ์‰ฌ์•Œ๋ฆผ ์ „์†ก sendNotifications(); - int updated = roomCommandPort.updateRoomState(RoomStatus.RECRUITING, RoomStatus.IN_PROGRESS); + int updated = roomCommandPort.updateRoomStateFromRecruitingToProgress(); log.info("[RoomState] IN_PROGRESS๋กœ ๋ณ€๊ฒฝ๋œ ๊ฑด์ˆ˜={}", updated); } private void sendNotifications() { - List targetRooms = roomCommandPort.findProgressTargetRooms(RoomStatus.RECRUITING); + List targetRooms = roomCommandPort.findProgressTargetRooms(); for (Room room : targetRooms) { List targetUsers = roomParticipantCommandPort.findAllByRoomId(room.getId()); for (RoomParticipant participant : targetUsers) { From 04f03ea8a868285a617d03e28a17f9b9af91e594 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Mon, 8 Sep 2025 17:14:32 +0900 Subject: [PATCH 86/93] =?UTF-8?q?[refactor]=20Spring=20Profile=20=EB=B3=84?= =?UTF-8?q?=20=EB=A1=9C=EA=B7=B8=20=EC=B6=9C=EB=A0=A5=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../out/firebase/FakeFirebaseAdapter.java | 7 +- .../adapter/out/firebase/FirebaseAdapter.java | 64 ++++++++++++++++++- 2 files changed, 65 insertions(+), 6 deletions(-) diff --git a/src/main/java/konkuk/thip/message/adapter/out/firebase/FakeFirebaseAdapter.java b/src/main/java/konkuk/thip/message/adapter/out/firebase/FakeFirebaseAdapter.java index 19e7204d1..0fe577bbd 100644 --- a/src/main/java/konkuk/thip/message/adapter/out/firebase/FakeFirebaseAdapter.java +++ b/src/main/java/konkuk/thip/message/adapter/out/firebase/FakeFirebaseAdapter.java @@ -14,13 +14,14 @@ @Profile("local | test") @RequiredArgsConstructor public class FakeFirebaseAdapter implements FirebaseMessagingPort { + @Override public void send(Message message, String fcmToken, String deviceId) { - log.info("FirebaseAdapter.send()"); + log.info("[FakeFCM:SEND] token={} device={} message={}", fcmToken, deviceId, message); } @Override public void sendBatch(List messages, List fcmTokens, List deviceIds) { - log.info("FirebaseAdapter.sendBatch()"); + log.info("[FakeFCM:BATCH] count={} tokens={} devices={}", messages.size(), fcmTokens, deviceIds); } -} +} \ No newline at end of file diff --git a/src/main/java/konkuk/thip/message/adapter/out/firebase/FirebaseAdapter.java b/src/main/java/konkuk/thip/message/adapter/out/firebase/FirebaseAdapter.java index b33fa45ab..1d7f64a83 100644 --- a/src/main/java/konkuk/thip/message/adapter/out/firebase/FirebaseAdapter.java +++ b/src/main/java/konkuk/thip/message/adapter/out/firebase/FirebaseAdapter.java @@ -5,6 +5,7 @@ import konkuk.thip.message.application.port.out.FirebaseMessagingPort; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; @@ -18,11 +19,16 @@ public class FirebaseAdapter implements FirebaseMessagingPort { private final FirebaseMessaging firebaseMessaging; + @Value("${server.profile}") + private String profile; + @Override public void send(Message message, String fcmToken, String deviceId) { try { - firebaseMessaging.send(message); + String messageId = firebaseMessaging.send(message); + log.debug("[FCM:SEND] ok id={} token={} device={}", messageId, maskDependingProfile(fcmToken), maskDependingProfile(deviceId)); } catch (FirebaseMessagingException e) { + log.warn("[FCM:SEND] fail token={} device={} code={} msg={}", maskDependingProfile(fcmToken), maskDependingProfile(deviceId), e.getMessagingErrorCode(), e.getMessage()); throw new FirebaseException(e); } } @@ -36,13 +42,65 @@ public void sendBatch(List messages, List fcmTokens, List responses = batchResponse.getResponses(); + for (int i = 0; i < responses.size(); i++) { + SendResponse sr = responses.get(i); + String token = fcmTokens.get(i); + String device = deviceIds.get(i); + + if (sr.isSuccessful()) { + log.debug("[FCM:BATCH] ok id={} token={} device={}", sr.getMessageId(), maskDependingProfile(token), maskDependingProfile(device)); + } else { + Exception ex = sr.getException(); + if (ex instanceof FirebaseMessagingException fme) { + log.warn("[FCM:BATCH] fail token={} device={} code={} msg={}", maskDependingProfile(token), maskDependingProfile(device), fme.getMessagingErrorCode(), fme.getMessage()); + } else { + log.warn("[FCM:BATCH] fail token={} device={} msg={}", maskDependingProfile(token), maskDependingProfile(device), ex.getMessage()); + } + } + } + if (batchResponse.getFailureCount() > 0) { log.warn("[FCM:BATCH] ์ผ๋ถ€ ๋ฉ”์‹œ์ง€ ์ „์†ก ์‹คํŒจ: {}/{}", batchResponse.getFailureCount(), messages.size()); throw new FirebaseException(); } } catch (FirebaseMessagingException e) { - log.warn("[FCM:BATCH] ๋ฉ”์‹œ์ง€ ์ „์†ก ์‹คํŒจ: {}", e.getMessage()); + log.warn("[FCM:BATCH] ๋ฉ”์‹œ์ง€ ์ „์†ก ์‹คํŒจ: code={} msg={}", e.getMessagingErrorCode(), e.getMessage()); throw new FirebaseException(e); } } -} + + /** + * ํ”„๋กœํŒŒ์ผ๋ณ„ ๋งˆ์Šคํ‚น ์ •์ฑ… + * - dev: ์›๋ฌธ ๊ทธ๋Œ€๋กœ ๋…ธ์ถœ + * - prod: ์ „์ฒด ๊ธธ์ด์˜ ์ ˆ๋ฐ˜์„ '*'๋กœ ์น˜ํ™˜(์น˜ํ™˜๋œ ๊ฐœ์ˆ˜๋งŒํผ ๋ณ„ํ‘œ๊ฐ€ ๋ณด์ด๋„๋ก), ๋‚˜๋จธ์ง€๋Š” ์•ž/๋’ค๋ฅผ ๊ท ๋“ฑํ•˜๊ฒŒ ๋…ธ์ถœ + */ + private String maskDependingProfile(String value) { + if (isDev()) return value; + return maskHalf(value); + } + + private boolean isDev() { + return profile != null && profile.trim().equalsIgnoreCase("dev"); + } + + /** + * ์ „์ฒด ๊ธธ์ด์˜ ์ ˆ๋ฐ˜์„ '*'๋กœ ์น˜ํ™˜ํ•˜๊ณ , ๋‚จ์€ ์ ˆ๋ฐ˜์€ ์•ž/๋’ค๋ฅผ ๊ท ๋“ฑ ๋ถ„ํ• ํ•ด ๋…ธ์ถœ + * ์˜ˆ) abcdefghij(10) -> ab*****hij (์•ž 2, ์ค‘๊ฐ„ 5*, ๋’ค 3) + */ + private String maskHalf(String s) { + if (s == null || s.isEmpty()) return "null"; + int len = s.length(); + if (len <= 4) return "*".repeat(len); // ๋„ˆ๋ฌด ์งง์œผ๋ฉด ์ „๋ถ€ ๋งˆ์Šคํ‚น + + int maskLen = len / 2; // ์ ˆ๋ฐ˜ ๋งˆ์Šคํ‚น + int visible = len - maskLen; // ๋ณด์ด๋Š” ๊ธธ์ด + int left = visible / 2; // ์•ž์ชฝ ๋ณด์ด๋Š” ๊ธธ์ด + int right = visible - left; // ๋’ค์ชฝ ๋ณด์ด๋Š” ๊ธธ์ด + + String prefix = s.substring(0, left); + String stars = "*".repeat(maskLen); + String suffix = s.substring(len - right); + return prefix + stars + suffix; + } +} \ No newline at end of file From 056daf3e19e0378d9a87d9ef72a9c3b4cc962944 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Mon, 8 Sep 2025 17:14:51 +0900 Subject: [PATCH 87/93] =?UTF-8?q?[refactor]=20Feed=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=EC=97=90=EC=84=9C=20PostQueryDto=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=20=EB=A1=9C=EC=A7=81=20=EC=82=AD=EC=A0=9C=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FeedCommandPersistenceAdapter.java | 5 ----- .../repository/FeedQueryRepository.java | 3 --- .../repository/FeedQueryRepositoryImpl.java | 15 --------------- .../application/port/out/FeedCommandPort.java | 3 --- 4 files changed, 26 deletions(-) diff --git a/src/main/java/konkuk/thip/feed/adapter/out/persistence/FeedCommandPersistenceAdapter.java b/src/main/java/konkuk/thip/feed/adapter/out/persistence/FeedCommandPersistenceAdapter.java index 3295eafe7..3bd038fb7 100644 --- a/src/main/java/konkuk/thip/feed/adapter/out/persistence/FeedCommandPersistenceAdapter.java +++ b/src/main/java/konkuk/thip/feed/adapter/out/persistence/FeedCommandPersistenceAdapter.java @@ -81,11 +81,6 @@ public void deleteSavedFeed(Long userId, Long feedId) { savedFeedJpaRepository.deleteByUserIdAndFeedId(userId, feedId); } - @Override - public PostQueryDto getPostQueryDtoById(Long postId) { - return feedJpaRepository.getPostQueryDtoByPostId(postId); - } - @Override public void delete(Feed feed) { FeedJpaEntity feedJpaEntity = feedJpaRepository.findByPostId(feed.getId()) diff --git a/src/main/java/konkuk/thip/feed/adapter/out/persistence/repository/FeedQueryRepository.java b/src/main/java/konkuk/thip/feed/adapter/out/persistence/repository/FeedQueryRepository.java index 9f7db6baf..a9b2fcfdc 100644 --- a/src/main/java/konkuk/thip/feed/adapter/out/persistence/repository/FeedQueryRepository.java +++ b/src/main/java/konkuk/thip/feed/adapter/out/persistence/repository/FeedQueryRepository.java @@ -1,7 +1,6 @@ package konkuk.thip.feed.adapter.out.persistence.repository; import konkuk.thip.feed.application.port.out.dto.FeedQueryDto; -import konkuk.thip.post.application.port.out.dto.PostQueryDto; import java.time.LocalDateTime; import java.util.List; @@ -25,6 +24,4 @@ public interface FeedQueryRepository { List findLatestPublicFeedCreatorsIn(Set userIds, int size); List findSavedFeedsByCreatedAt(Long userId, LocalDateTime lastCreatedAt, int size); - - PostQueryDto getPostQueryDtoByPostId(Long postId); } diff --git a/src/main/java/konkuk/thip/feed/adapter/out/persistence/repository/FeedQueryRepositoryImpl.java b/src/main/java/konkuk/thip/feed/adapter/out/persistence/repository/FeedQueryRepositoryImpl.java index 9ca87dc50..fbd079a4a 100644 --- a/src/main/java/konkuk/thip/feed/adapter/out/persistence/repository/FeedQueryRepositoryImpl.java +++ b/src/main/java/konkuk/thip/feed/adapter/out/persistence/repository/FeedQueryRepositoryImpl.java @@ -390,21 +390,6 @@ public List findSavedFeedsByCreatedAt(Long userId, LocalDateTime l .fetch(); } - @Override - public PostQueryDto getPostQueryDtoByPostId(Long postId) { - return jpaQueryFactory - .select(new QPostQueryDto( - feed.postId, - feed.userJpaEntity.userId, - feed.dtype, - Expressions.nullExpression(), - Expressions.nullExpression() - )) - .from(feed) - .where(feed.postId.eq(postId)) - .fetchOne(); - } - /** * SavedFeed ์ „์šฉ DTO ๋งคํ•‘ */ diff --git a/src/main/java/konkuk/thip/feed/application/port/out/FeedCommandPort.java b/src/main/java/konkuk/thip/feed/application/port/out/FeedCommandPort.java index d24b332b9..40dea9122 100644 --- a/src/main/java/konkuk/thip/feed/application/port/out/FeedCommandPort.java +++ b/src/main/java/konkuk/thip/feed/application/port/out/FeedCommandPort.java @@ -3,7 +3,6 @@ import konkuk.thip.common.exception.EntityNotFoundException; import konkuk.thip.feed.domain.Feed; -import konkuk.thip.post.application.port.out.dto.PostQueryDto; import java.util.Optional; @@ -20,6 +19,4 @@ default Feed getByIdOrThrow(Long id) { void delete(Feed feed); void saveSavedFeed(Long userId, Long feedId); void deleteSavedFeed(Long userId, Long feedId); - - PostQueryDto getPostQueryDtoById(Long postId); } From e38c748590134d18b50d88b0642ea1755905e8fd Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Mon, 8 Sep 2025 17:15:01 +0900 Subject: [PATCH 88/93] =?UTF-8?q?[refactor]=20RoomPost=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=EC=97=90=EC=84=9C=20PostQueryDto=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EB=A1=9C=EC=A7=81=20=EC=82=AD=EC=A0=9C=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RecordCommandPersistenceAdapter.java | 10 ++---- .../record/RecordQueryRepository.java | 3 -- .../record/RecordQueryRepositoryImpl.java | 35 ------------------- .../port/out/RecordCommandPort.java | 3 -- 4 files changed, 2 insertions(+), 49 deletions(-) diff --git a/src/main/java/konkuk/thip/roompost/adapter/out/persistence/RecordCommandPersistenceAdapter.java b/src/main/java/konkuk/thip/roompost/adapter/out/persistence/RecordCommandPersistenceAdapter.java index ae26a63c5..6acb8248c 100644 --- a/src/main/java/konkuk/thip/roompost/adapter/out/persistence/RecordCommandPersistenceAdapter.java +++ b/src/main/java/konkuk/thip/roompost/adapter/out/persistence/RecordCommandPersistenceAdapter.java @@ -1,14 +1,13 @@ package konkuk.thip.roompost.adapter.out.persistence; import konkuk.thip.common.exception.EntityNotFoundException; -import konkuk.thip.post.application.port.out.dto.PostQueryDto; +import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; +import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.roompost.adapter.out.jpa.RecordJpaEntity; import konkuk.thip.roompost.adapter.out.mapper.RecordMapper; import konkuk.thip.roompost.adapter.out.persistence.repository.record.RecordJpaRepository; import konkuk.thip.roompost.application.port.out.RecordCommandPort; import konkuk.thip.roompost.domain.Record; -import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; -import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import lombok.RequiredArgsConstructor; @@ -58,11 +57,6 @@ public void delete(Record record) { recordJpaRepository.save(recordJpaEntity); } - @Override - public PostQueryDto getPostQueryDtoById(Long postId) { - return recordJpaRepository.getPostQueryDtoByPostId(postId); - } - @Override public void update(Record record) { RecordJpaEntity recordJpaEntity = recordJpaRepository.findByPostId(record.getId()).orElseThrow( diff --git a/src/main/java/konkuk/thip/roompost/adapter/out/persistence/repository/record/RecordQueryRepository.java b/src/main/java/konkuk/thip/roompost/adapter/out/persistence/repository/record/RecordQueryRepository.java index e1632d06c..936f14737 100644 --- a/src/main/java/konkuk/thip/roompost/adapter/out/persistence/repository/record/RecordQueryRepository.java +++ b/src/main/java/konkuk/thip/roompost/adapter/out/persistence/repository/record/RecordQueryRepository.java @@ -1,7 +1,6 @@ package konkuk.thip.roompost.adapter.out.persistence.repository.record; import konkuk.thip.common.util.Cursor; -import konkuk.thip.post.application.port.out.dto.PostQueryDto; import konkuk.thip.roompost.adapter.out.persistence.RoomPostSortType; import konkuk.thip.roompost.application.port.out.dto.RoomPostQueryDto; @@ -12,6 +11,4 @@ public interface RecordQueryRepository { List findMyRecords(Long roomId, Long userId, Cursor cursor); List findGroupRecordsOrderBySortType(Long roomId, Long userId, Cursor cursor, Integer pageStart, Integer pageEnd, Boolean isOverview, RoomPostSortType roomPostSortType); - - PostQueryDto getPostQueryDtoByPostId(Long postId); } diff --git a/src/main/java/konkuk/thip/roompost/adapter/out/persistence/repository/record/RecordQueryRepositoryImpl.java b/src/main/java/konkuk/thip/roompost/adapter/out/persistence/repository/record/RecordQueryRepositoryImpl.java index fbe50c2b8..2376fc136 100644 --- a/src/main/java/konkuk/thip/roompost/adapter/out/persistence/repository/record/RecordQueryRepositoryImpl.java +++ b/src/main/java/konkuk/thip/roompost/adapter/out/persistence/repository/record/RecordQueryRepositoryImpl.java @@ -7,8 +7,6 @@ import com.querydsl.jpa.impl.JPAQueryFactory; import konkuk.thip.common.util.Cursor; import konkuk.thip.post.adapter.out.jpa.QPostJpaEntity; -import konkuk.thip.post.application.port.out.dto.PostQueryDto; -import konkuk.thip.post.application.port.out.dto.QPostQueryDto; import konkuk.thip.roompost.adapter.out.jpa.QRecordJpaEntity; import konkuk.thip.roompost.adapter.out.jpa.QVoteJpaEntity; import konkuk.thip.roompost.adapter.out.persistence.RoomPostSortType; @@ -201,37 +199,4 @@ private QRoomPostQueryDto selectPostQueryDto() { isOverviewExpr().eq(1) ); } - - @Override - public PostQueryDto getPostQueryDtoByPostId(Long postId) { - return queryFactory - .select(new QPostQueryDto( - post.postId, - post.userJpaEntity.userId, - post.dtype, - pageExprForDto(), // dtype์— ๋”ฐ๋ผ Record/Vote์˜ page - roomIdExprForDto() // dtype์— ๋”ฐ๋ผ Record/Vote์˜ roomId - )) - .from(post) - .where(post.postId.eq(postId)) - .fetchOne(); - } - - private NumberExpression pageExprForDto() { - return new CaseBuilder() - .when(post.dtype.eq(RECORD.getType())) - .then(treat(post, QRecordJpaEntity.class).page) - .when(post.dtype.eq(VOTE.getType())) - .then(treat(post, QVoteJpaEntity.class).page) - .otherwise((Integer) null); - } - - private NumberExpression roomIdExprForDto() { - return new CaseBuilder() - .when(post.dtype.eq(RECORD.getType())) - .then(treat(post, QRecordJpaEntity.class).roomJpaEntity.roomId) - .when(post.dtype.eq(VOTE.getType())) - .then(treat(post, QVoteJpaEntity.class).roomJpaEntity.roomId) - .otherwise((Long) null); - } } diff --git a/src/main/java/konkuk/thip/roompost/application/port/out/RecordCommandPort.java b/src/main/java/konkuk/thip/roompost/application/port/out/RecordCommandPort.java index ed3aacb71..16b5ceb9a 100644 --- a/src/main/java/konkuk/thip/roompost/application/port/out/RecordCommandPort.java +++ b/src/main/java/konkuk/thip/roompost/application/port/out/RecordCommandPort.java @@ -2,7 +2,6 @@ import konkuk.thip.common.exception.EntityNotFoundException; -import konkuk.thip.post.application.port.out.dto.PostQueryDto; import konkuk.thip.roompost.domain.Record; import java.util.Optional; @@ -23,6 +22,4 @@ default Record getByIdOrThrow(Long id) { } void delete(Record record); - - PostQueryDto getPostQueryDtoById(Long postId); } From 6e38bdd453ee22b37980b1705e4f1b5ff68f6a4a Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Mon, 8 Sep 2025 17:15:16 +0900 Subject: [PATCH 89/93] =?UTF-8?q?[refactor]=20Post=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=EC=97=90=20PostQueryDto=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PostQueryPersistenceAdapter.java | 30 ++++++++ .../repository/PostJpaRepository.java | 9 +++ .../repository/PostQueryRepository.java | 10 +++ .../repository/PostQueryRepositoryImpl.java | 73 +++++++++++++++++++ .../application/port/out/PostQueryPort.java | 10 +++ .../service/handler/PostHandler.java | 19 +++-- 6 files changed, 143 insertions(+), 8 deletions(-) create mode 100644 src/main/java/konkuk/thip/post/adapter/out/persistence/PostQueryPersistenceAdapter.java create mode 100644 src/main/java/konkuk/thip/post/adapter/out/persistence/repository/PostJpaRepository.java create mode 100644 src/main/java/konkuk/thip/post/adapter/out/persistence/repository/PostQueryRepository.java create mode 100644 src/main/java/konkuk/thip/post/adapter/out/persistence/repository/PostQueryRepositoryImpl.java create mode 100644 src/main/java/konkuk/thip/post/application/port/out/PostQueryPort.java diff --git a/src/main/java/konkuk/thip/post/adapter/out/persistence/PostQueryPersistenceAdapter.java b/src/main/java/konkuk/thip/post/adapter/out/persistence/PostQueryPersistenceAdapter.java new file mode 100644 index 000000000..966a04f04 --- /dev/null +++ b/src/main/java/konkuk/thip/post/adapter/out/persistence/PostQueryPersistenceAdapter.java @@ -0,0 +1,30 @@ +package konkuk.thip.post.adapter.out.persistence; + +import konkuk.thip.post.adapter.out.persistence.repository.PostJpaRepository; +import konkuk.thip.post.application.port.out.PostQueryPort; +import konkuk.thip.post.application.port.out.dto.PostQueryDto; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +@Repository +@RequiredArgsConstructor +public class PostQueryPersistenceAdapter implements PostQueryPort { + + private final PostJpaRepository postJpaRepository; + + @Override + public PostQueryDto getPostQueryDtoByFeedId(Long feedId) { + return postJpaRepository.getPostQueryDtoByFeedId(feedId); + } + + @Override + public PostQueryDto getPostQueryDtoByRecordId(Long recordId) { + return postJpaRepository.getPostQueryDtoByRecordId(recordId); + } + + @Override + public PostQueryDto getPostQueryDtoByVoteId(Long voteId) { + return postJpaRepository.getPostQueryDtoByVoteId(voteId); + } + +} diff --git a/src/main/java/konkuk/thip/post/adapter/out/persistence/repository/PostJpaRepository.java b/src/main/java/konkuk/thip/post/adapter/out/persistence/repository/PostJpaRepository.java new file mode 100644 index 000000000..2e7b0f394 --- /dev/null +++ b/src/main/java/konkuk/thip/post/adapter/out/persistence/repository/PostJpaRepository.java @@ -0,0 +1,9 @@ +package konkuk.thip.post.adapter.out.persistence.repository; + +import konkuk.thip.post.adapter.out.jpa.PostJpaEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface PostJpaRepository extends JpaRepository, PostQueryRepository { +} diff --git a/src/main/java/konkuk/thip/post/adapter/out/persistence/repository/PostQueryRepository.java b/src/main/java/konkuk/thip/post/adapter/out/persistence/repository/PostQueryRepository.java new file mode 100644 index 000000000..fd7890345 --- /dev/null +++ b/src/main/java/konkuk/thip/post/adapter/out/persistence/repository/PostQueryRepository.java @@ -0,0 +1,10 @@ +package konkuk.thip.post.adapter.out.persistence.repository; + +import konkuk.thip.post.application.port.out.dto.PostQueryDto; + +public interface PostQueryRepository { + PostQueryDto getPostQueryDtoByFeedId(Long feedId); + + PostQueryDto getPostQueryDtoByRecordId(Long recordId); + PostQueryDto getPostQueryDtoByVoteId(Long voteId); +} diff --git a/src/main/java/konkuk/thip/post/adapter/out/persistence/repository/PostQueryRepositoryImpl.java b/src/main/java/konkuk/thip/post/adapter/out/persistence/repository/PostQueryRepositoryImpl.java new file mode 100644 index 000000000..12d4ce3fd --- /dev/null +++ b/src/main/java/konkuk/thip/post/adapter/out/persistence/repository/PostQueryRepositoryImpl.java @@ -0,0 +1,73 @@ +package konkuk.thip.post.adapter.out.persistence.repository; + +import com.querydsl.core.types.dsl.Expressions; +import com.querydsl.jpa.impl.JPAQueryFactory; +import konkuk.thip.feed.adapter.out.jpa.QFeedJpaEntity; +import konkuk.thip.post.adapter.out.jpa.QPostJpaEntity; +import konkuk.thip.post.application.port.out.dto.PostQueryDto; +import konkuk.thip.post.application.port.out.dto.QPostQueryDto; +import konkuk.thip.roompost.adapter.out.jpa.QRecordJpaEntity; +import konkuk.thip.roompost.adapter.out.jpa.QVoteJpaEntity; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +import static com.querydsl.jpa.JPAExpressions.treat; +import static konkuk.thip.post.domain.PostType.*; + +@Repository +@RequiredArgsConstructor +public class PostQueryRepositoryImpl implements PostQueryRepository { + + private final QPostJpaEntity post = QPostJpaEntity.postJpaEntity; + private final QFeedJpaEntity feed = QFeedJpaEntity.feedJpaEntity; + + private final JPAQueryFactory jpaQueryFactory; + + @Override + public PostQueryDto getPostQueryDtoByFeedId(Long feedId) { + return jpaQueryFactory + .select(new QPostQueryDto( + feed.postId, + feed.userJpaEntity.userId, + feed.dtype, + Expressions.nullExpression(), + Expressions.nullExpression() + )) + .from(feed) + .where(feed.postId.eq(feedId)) + .where(feed.dtype.eq(FEED.getType())) + .fetchOne(); + } + + @Override + public PostQueryDto getPostQueryDtoByRecordId(Long recordId) { + return jpaQueryFactory + .select(new QPostQueryDto( + post.postId, + post.userJpaEntity.userId, + post.dtype, + treat(post, QRecordJpaEntity.class).page, // Record์˜ page + treat(post, QRecordJpaEntity.class).roomJpaEntity.roomId // Record์˜ roomId + )) + .from(post) + .where(post.postId.eq(recordId)) + .where(post.dtype.eq(RECORD.getType())) + .fetchOne(); + } + + @Override + public PostQueryDto getPostQueryDtoByVoteId(Long voteId) { + return jpaQueryFactory + .select(new QPostQueryDto( + post.postId, + post.userJpaEntity.userId, + post.dtype, + treat(post, QVoteJpaEntity.class).page, // Vote์˜ page + treat(post, QVoteJpaEntity.class).roomJpaEntity.roomId // Vote์˜ roomId + )) + .from(post) + .where(post.postId.eq(voteId)) + .where(post.dtype.eq(VOTE.getType())) + .fetchOne(); + } +} diff --git a/src/main/java/konkuk/thip/post/application/port/out/PostQueryPort.java b/src/main/java/konkuk/thip/post/application/port/out/PostQueryPort.java new file mode 100644 index 000000000..7682383d3 --- /dev/null +++ b/src/main/java/konkuk/thip/post/application/port/out/PostQueryPort.java @@ -0,0 +1,10 @@ +package konkuk.thip.post.application.port.out; + +import konkuk.thip.post.application.port.out.dto.PostQueryDto; + +public interface PostQueryPort { + PostQueryDto getPostQueryDtoByFeedId(Long feedId); + + PostQueryDto getPostQueryDtoByRecordId(Long recordId); + PostQueryDto getPostQueryDtoByVoteId(Long voteId); +} diff --git a/src/main/java/konkuk/thip/post/application/service/handler/PostHandler.java b/src/main/java/konkuk/thip/post/application/service/handler/PostHandler.java index c7ece4d65..7460bc210 100644 --- a/src/main/java/konkuk/thip/post/application/service/handler/PostHandler.java +++ b/src/main/java/konkuk/thip/post/application/service/handler/PostHandler.java @@ -1,14 +1,15 @@ package konkuk.thip.post.application.service.handler; import konkuk.thip.common.annotation.application.HelperService; +import konkuk.thip.feed.application.port.out.FeedCommandPort; +import konkuk.thip.feed.domain.Feed; +import konkuk.thip.post.application.port.out.PostQueryPort; import konkuk.thip.post.application.port.out.dto.PostQueryDto; import konkuk.thip.post.domain.CountUpdatable; import konkuk.thip.post.domain.PostType; -import konkuk.thip.feed.application.port.out.FeedCommandPort; -import konkuk.thip.feed.domain.Feed; import konkuk.thip.roompost.application.port.out.RecordCommandPort; -import konkuk.thip.roompost.domain.Record; import konkuk.thip.roompost.application.port.out.VoteCommandPort; +import konkuk.thip.roompost.domain.Record; import konkuk.thip.roompost.domain.Vote; import lombok.RequiredArgsConstructor; @@ -20,6 +21,8 @@ public class PostHandler { private final RecordCommandPort recordCommandPort; private final VoteCommandPort voteCommandPort; + private final PostQueryPort portQueryPort; + public CountUpdatable findPost(PostType type, Long postId) { return switch (type) { case FEED -> feedCommandPort.getByIdOrThrow(postId); @@ -37,10 +40,10 @@ public void updatePost(PostType type, CountUpdatable post) { } public PostQueryDto getPostQueryDto(PostType type, Long postId) { - if (type == PostType.FEED) { - return feedCommandPort.getPostQueryDtoById(postId); - } - - return recordCommandPort.getPostQueryDtoById(postId); + return switch (type) { + case FEED -> portQueryPort.getPostQueryDtoByFeedId(postId); + case RECORD -> portQueryPort.getPostQueryDtoByRecordId(postId); + case VOTE -> portQueryPort.getPostQueryDtoByVoteId(postId); + }; } } From 738d5cb468818920a87aa05a5c7251dfdb4a50ed Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Mon, 8 Sep 2025 17:15:59 +0900 Subject: [PATCH 90/93] =?UTF-8?q?[refactor]=20PostLikeJpaRepository=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=20=EC=9D=B4=EB=8F=99=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../out/persistence/PostLikeCommandPersistenceAdapter.java | 1 + .../out/persistence/PostLikeQueryPersistenceAdapter.java | 1 + .../out/persistence/{ => repository}/PostLikeJpaRepository.java | 2 +- .../thip/feed/adapter/in/web/BasicFeedShowAllApiTest.java | 2 +- .../thip/feed/adapter/in/web/FeedChangeLikeStatusApiTest.java | 2 +- .../java/konkuk/thip/feed/adapter/in/web/FeedDeleteApiTest.java | 2 +- .../thip/feed/adapter/in/web/FeedRelatedWithBookApiTest.java | 2 +- .../konkuk/thip/feed/adapter/in/web/FeedShowMineApiTest.java | 2 +- .../thip/feed/adapter/in/web/FeedShowSavedListApiTest.java | 2 +- .../konkuk/thip/feed/adapter/in/web/FeedShowSingleApiTest.java | 2 +- .../thip/feed/adapter/in/web/FeedShowSpecificUserApiTest.java | 2 +- .../adapter/in/web/FollowingPriorityFeedShowAllApiTest.java | 2 +- .../room/adapter/in/web/RoomPostChangeLikeStatusApiTest.java | 2 +- .../thip/roompost/adapter/in/web/RecordDeleteApiTest.java | 2 +- .../konkuk/thip/roompost/adapter/in/web/VoteDeleteApiTest.java | 2 +- .../konkuk/thip/user/adapter/in/web/UserReactionApiTest.java | 2 +- 16 files changed, 16 insertions(+), 14 deletions(-) rename src/main/java/konkuk/thip/post/adapter/out/persistence/{ => repository}/PostLikeJpaRepository.java (96%) diff --git a/src/main/java/konkuk/thip/post/adapter/out/persistence/PostLikeCommandPersistenceAdapter.java b/src/main/java/konkuk/thip/post/adapter/out/persistence/PostLikeCommandPersistenceAdapter.java index e4f9d2057..9527d19ea 100644 --- a/src/main/java/konkuk/thip/post/adapter/out/persistence/PostLikeCommandPersistenceAdapter.java +++ b/src/main/java/konkuk/thip/post/adapter/out/persistence/PostLikeCommandPersistenceAdapter.java @@ -1,6 +1,7 @@ package konkuk.thip.post.adapter.out.persistence; import konkuk.thip.common.exception.EntityNotFoundException; +import konkuk.thip.post.adapter.out.persistence.repository.PostLikeJpaRepository; import konkuk.thip.post.domain.PostType; import konkuk.thip.feed.adapter.out.persistence.repository.FeedJpaRepository; import konkuk.thip.post.adapter.out.jpa.PostJpaEntity; diff --git a/src/main/java/konkuk/thip/post/adapter/out/persistence/PostLikeQueryPersistenceAdapter.java b/src/main/java/konkuk/thip/post/adapter/out/persistence/PostLikeQueryPersistenceAdapter.java index cd3975869..51c10edbe 100644 --- a/src/main/java/konkuk/thip/post/adapter/out/persistence/PostLikeQueryPersistenceAdapter.java +++ b/src/main/java/konkuk/thip/post/adapter/out/persistence/PostLikeQueryPersistenceAdapter.java @@ -1,5 +1,6 @@ package konkuk.thip.post.adapter.out.persistence; +import konkuk.thip.post.adapter.out.persistence.repository.PostLikeJpaRepository; import konkuk.thip.post.application.port.out.PostLikeQueryPort; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; diff --git a/src/main/java/konkuk/thip/post/adapter/out/persistence/PostLikeJpaRepository.java b/src/main/java/konkuk/thip/post/adapter/out/persistence/repository/PostLikeJpaRepository.java similarity index 96% rename from src/main/java/konkuk/thip/post/adapter/out/persistence/PostLikeJpaRepository.java rename to src/main/java/konkuk/thip/post/adapter/out/persistence/repository/PostLikeJpaRepository.java index 8b291e553..be626ac38 100644 --- a/src/main/java/konkuk/thip/post/adapter/out/persistence/PostLikeJpaRepository.java +++ b/src/main/java/konkuk/thip/post/adapter/out/persistence/repository/PostLikeJpaRepository.java @@ -1,4 +1,4 @@ -package konkuk.thip.post.adapter.out.persistence; +package konkuk.thip.post.adapter.out.persistence.repository; import konkuk.thip.post.adapter.out.jpa.PostLikeJpaEntity; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/src/test/java/konkuk/thip/feed/adapter/in/web/BasicFeedShowAllApiTest.java b/src/test/java/konkuk/thip/feed/adapter/in/web/BasicFeedShowAllApiTest.java index bf8dfb4a8..cd6c59e9c 100644 --- a/src/test/java/konkuk/thip/feed/adapter/in/web/BasicFeedShowAllApiTest.java +++ b/src/test/java/konkuk/thip/feed/adapter/in/web/BasicFeedShowAllApiTest.java @@ -6,7 +6,7 @@ import konkuk.thip.feed.adapter.out.jpa.FeedJpaEntity; import konkuk.thip.feed.adapter.out.persistence.repository.FeedJpaRepository; import konkuk.thip.post.adapter.out.jpa.PostLikeJpaEntity; -import konkuk.thip.post.adapter.out.persistence.PostLikeJpaRepository; +import konkuk.thip.post.adapter.out.persistence.repository.PostLikeJpaRepository; import konkuk.thip.feed.adapter.out.jpa.SavedFeedJpaEntity; import konkuk.thip.feed.adapter.out.persistence.repository.SavedFeedJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; diff --git a/src/test/java/konkuk/thip/feed/adapter/in/web/FeedChangeLikeStatusApiTest.java b/src/test/java/konkuk/thip/feed/adapter/in/web/FeedChangeLikeStatusApiTest.java index 921c22204..ca31c8511 100644 --- a/src/test/java/konkuk/thip/feed/adapter/in/web/FeedChangeLikeStatusApiTest.java +++ b/src/test/java/konkuk/thip/feed/adapter/in/web/FeedChangeLikeStatusApiTest.java @@ -7,7 +7,7 @@ import konkuk.thip.feed.adapter.in.web.request.FeedIsLikeRequest; import konkuk.thip.feed.adapter.out.jpa.FeedJpaEntity; import konkuk.thip.feed.adapter.out.persistence.repository.FeedJpaRepository; -import konkuk.thip.post.adapter.out.persistence.PostLikeJpaRepository; +import konkuk.thip.post.adapter.out.persistence.repository.PostLikeJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import konkuk.thip.user.domain.value.Alias; diff --git a/src/test/java/konkuk/thip/feed/adapter/in/web/FeedDeleteApiTest.java b/src/test/java/konkuk/thip/feed/adapter/in/web/FeedDeleteApiTest.java index 8b39285be..0d4627b3d 100644 --- a/src/test/java/konkuk/thip/feed/adapter/in/web/FeedDeleteApiTest.java +++ b/src/test/java/konkuk/thip/feed/adapter/in/web/FeedDeleteApiTest.java @@ -9,7 +9,7 @@ import konkuk.thip.feed.adapter.out.jpa.FeedJpaEntity; import konkuk.thip.feed.adapter.out.persistence.repository.FeedJpaRepository; import konkuk.thip.feed.adapter.out.persistence.repository.SavedFeedJpaRepository; -import konkuk.thip.post.adapter.out.persistence.PostLikeJpaRepository; +import konkuk.thip.post.adapter.out.persistence.repository.PostLikeJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import konkuk.thip.user.domain.value.Alias; diff --git a/src/test/java/konkuk/thip/feed/adapter/in/web/FeedRelatedWithBookApiTest.java b/src/test/java/konkuk/thip/feed/adapter/in/web/FeedRelatedWithBookApiTest.java index 1c5ec79b0..9ee2dfab1 100644 --- a/src/test/java/konkuk/thip/feed/adapter/in/web/FeedRelatedWithBookApiTest.java +++ b/src/test/java/konkuk/thip/feed/adapter/in/web/FeedRelatedWithBookApiTest.java @@ -9,7 +9,7 @@ import konkuk.thip.feed.adapter.out.persistence.repository.FeedJpaRepository; import konkuk.thip.feed.adapter.out.persistence.repository.SavedFeedJpaRepository; import konkuk.thip.post.adapter.out.jpa.PostLikeJpaEntity; -import konkuk.thip.post.adapter.out.persistence.PostLikeJpaRepository; +import konkuk.thip.post.adapter.out.persistence.repository.PostLikeJpaRepository; import konkuk.thip.room.domain.value.Category; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; import konkuk.thip.user.domain.value.UserRole; diff --git a/src/test/java/konkuk/thip/feed/adapter/in/web/FeedShowMineApiTest.java b/src/test/java/konkuk/thip/feed/adapter/in/web/FeedShowMineApiTest.java index 2b5fb1b69..7636df682 100644 --- a/src/test/java/konkuk/thip/feed/adapter/in/web/FeedShowMineApiTest.java +++ b/src/test/java/konkuk/thip/feed/adapter/in/web/FeedShowMineApiTest.java @@ -5,7 +5,7 @@ import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.feed.adapter.out.jpa.FeedJpaEntity; import konkuk.thip.feed.adapter.out.persistence.repository.FeedJpaRepository; -import konkuk.thip.post.adapter.out.persistence.PostLikeJpaRepository; +import konkuk.thip.post.adapter.out.persistence.repository.PostLikeJpaRepository; import konkuk.thip.feed.adapter.out.persistence.repository.SavedFeedJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; diff --git a/src/test/java/konkuk/thip/feed/adapter/in/web/FeedShowSavedListApiTest.java b/src/test/java/konkuk/thip/feed/adapter/in/web/FeedShowSavedListApiTest.java index 4d3ff8597..a0dd6403c 100644 --- a/src/test/java/konkuk/thip/feed/adapter/in/web/FeedShowSavedListApiTest.java +++ b/src/test/java/konkuk/thip/feed/adapter/in/web/FeedShowSavedListApiTest.java @@ -8,7 +8,7 @@ import konkuk.thip.feed.adapter.out.persistence.repository.FeedJpaRepository; import konkuk.thip.feed.adapter.out.persistence.repository.SavedFeedJpaRepository; import konkuk.thip.post.adapter.out.jpa.PostLikeJpaEntity; -import konkuk.thip.post.adapter.out.persistence.PostLikeJpaRepository; +import konkuk.thip.post.adapter.out.persistence.repository.PostLikeJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import konkuk.thip.user.domain.value.Alias; diff --git a/src/test/java/konkuk/thip/feed/adapter/in/web/FeedShowSingleApiTest.java b/src/test/java/konkuk/thip/feed/adapter/in/web/FeedShowSingleApiTest.java index 244c43b52..450798708 100644 --- a/src/test/java/konkuk/thip/feed/adapter/in/web/FeedShowSingleApiTest.java +++ b/src/test/java/konkuk/thip/feed/adapter/in/web/FeedShowSingleApiTest.java @@ -8,7 +8,7 @@ import konkuk.thip.feed.adapter.out.persistence.repository.FeedJpaRepository; import konkuk.thip.feed.adapter.out.persistence.repository.SavedFeedJpaRepository; import konkuk.thip.feed.domain.value.Tag; -import konkuk.thip.post.adapter.out.persistence.PostLikeJpaRepository; +import konkuk.thip.post.adapter.out.persistence.repository.PostLikeJpaRepository; import konkuk.thip.room.domain.value.Category; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; diff --git a/src/test/java/konkuk/thip/feed/adapter/in/web/FeedShowSpecificUserApiTest.java b/src/test/java/konkuk/thip/feed/adapter/in/web/FeedShowSpecificUserApiTest.java index 59237330f..6701bfb82 100644 --- a/src/test/java/konkuk/thip/feed/adapter/in/web/FeedShowSpecificUserApiTest.java +++ b/src/test/java/konkuk/thip/feed/adapter/in/web/FeedShowSpecificUserApiTest.java @@ -6,7 +6,7 @@ import konkuk.thip.feed.adapter.out.jpa.FeedJpaEntity; import konkuk.thip.feed.adapter.out.persistence.repository.FeedJpaRepository; import konkuk.thip.post.adapter.out.jpa.PostLikeJpaEntity; -import konkuk.thip.post.adapter.out.persistence.PostLikeJpaRepository; +import konkuk.thip.post.adapter.out.persistence.repository.PostLikeJpaRepository; import konkuk.thip.feed.adapter.out.jpa.SavedFeedJpaEntity; import konkuk.thip.feed.adapter.out.persistence.repository.SavedFeedJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; diff --git a/src/test/java/konkuk/thip/feed/adapter/in/web/FollowingPriorityFeedShowAllApiTest.java b/src/test/java/konkuk/thip/feed/adapter/in/web/FollowingPriorityFeedShowAllApiTest.java index 62025dad9..4c4e1b3fb 100644 --- a/src/test/java/konkuk/thip/feed/adapter/in/web/FollowingPriorityFeedShowAllApiTest.java +++ b/src/test/java/konkuk/thip/feed/adapter/in/web/FollowingPriorityFeedShowAllApiTest.java @@ -6,7 +6,7 @@ import konkuk.thip.feed.adapter.out.jpa.FeedJpaEntity; import konkuk.thip.feed.adapter.out.persistence.repository.FeedJpaRepository; import konkuk.thip.post.adapter.out.jpa.PostLikeJpaEntity; -import konkuk.thip.post.adapter.out.persistence.PostLikeJpaRepository; +import konkuk.thip.post.adapter.out.persistence.repository.PostLikeJpaRepository; import konkuk.thip.feed.adapter.out.jpa.SavedFeedJpaEntity; import konkuk.thip.feed.adapter.out.persistence.repository.SavedFeedJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; diff --git a/src/test/java/konkuk/thip/room/adapter/in/web/RoomPostChangeLikeStatusApiTest.java b/src/test/java/konkuk/thip/room/adapter/in/web/RoomPostChangeLikeStatusApiTest.java index ff57ca399..9d2362577 100644 --- a/src/test/java/konkuk/thip/room/adapter/in/web/RoomPostChangeLikeStatusApiTest.java +++ b/src/test/java/konkuk/thip/room/adapter/in/web/RoomPostChangeLikeStatusApiTest.java @@ -6,7 +6,7 @@ import konkuk.thip.common.util.TestEntityFactory; import konkuk.thip.feed.adapter.out.jpa.FeedJpaEntity; import konkuk.thip.feed.adapter.out.persistence.repository.FeedJpaRepository; -import konkuk.thip.post.adapter.out.persistence.PostLikeJpaRepository; +import konkuk.thip.post.adapter.out.persistence.repository.PostLikeJpaRepository; import konkuk.thip.room.domain.value.Category; import konkuk.thip.roompost.adapter.out.jpa.RecordJpaEntity; import konkuk.thip.roompost.adapter.out.persistence.repository.record.RecordJpaRepository; diff --git a/src/test/java/konkuk/thip/roompost/adapter/in/web/RecordDeleteApiTest.java b/src/test/java/konkuk/thip/roompost/adapter/in/web/RecordDeleteApiTest.java index 1f150ee4b..d9d5a0696 100644 --- a/src/test/java/konkuk/thip/roompost/adapter/in/web/RecordDeleteApiTest.java +++ b/src/test/java/konkuk/thip/roompost/adapter/in/web/RecordDeleteApiTest.java @@ -6,7 +6,7 @@ import konkuk.thip.comment.adapter.out.persistence.repository.CommentJpaRepository; import konkuk.thip.comment.adapter.out.persistence.repository.CommentLikeJpaRepository; import konkuk.thip.common.util.TestEntityFactory; -import konkuk.thip.post.adapter.out.persistence.PostLikeJpaRepository; +import konkuk.thip.post.adapter.out.persistence.repository.PostLikeJpaRepository; import konkuk.thip.room.domain.value.Category; import konkuk.thip.roompost.adapter.out.jpa.RecordJpaEntity; import konkuk.thip.roompost.adapter.out.persistence.repository.record.RecordJpaRepository; diff --git a/src/test/java/konkuk/thip/roompost/adapter/in/web/VoteDeleteApiTest.java b/src/test/java/konkuk/thip/roompost/adapter/in/web/VoteDeleteApiTest.java index 0ed2a6af6..067a12d60 100644 --- a/src/test/java/konkuk/thip/roompost/adapter/in/web/VoteDeleteApiTest.java +++ b/src/test/java/konkuk/thip/roompost/adapter/in/web/VoteDeleteApiTest.java @@ -6,7 +6,7 @@ import konkuk.thip.comment.adapter.out.persistence.repository.CommentJpaRepository; import konkuk.thip.comment.adapter.out.persistence.repository.CommentLikeJpaRepository; import konkuk.thip.common.util.TestEntityFactory; -import konkuk.thip.post.adapter.out.persistence.PostLikeJpaRepository; +import konkuk.thip.post.adapter.out.persistence.repository.PostLikeJpaRepository; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; diff --git a/src/test/java/konkuk/thip/user/adapter/in/web/UserReactionApiTest.java b/src/test/java/konkuk/thip/user/adapter/in/web/UserReactionApiTest.java index 91d61fad3..06be8ae90 100644 --- a/src/test/java/konkuk/thip/user/adapter/in/web/UserReactionApiTest.java +++ b/src/test/java/konkuk/thip/user/adapter/in/web/UserReactionApiTest.java @@ -9,7 +9,7 @@ import konkuk.thip.feed.adapter.out.jpa.FeedJpaEntity; import konkuk.thip.feed.adapter.out.persistence.repository.FeedJpaRepository; import konkuk.thip.post.adapter.out.jpa.PostLikeJpaEntity; -import konkuk.thip.post.adapter.out.persistence.PostLikeJpaRepository; +import konkuk.thip.post.adapter.out.persistence.repository.PostLikeJpaRepository; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.domain.value.RoomParticipantRole; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; From 4f3e67180d80857b60767b0d2792af6a7fc4206c Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Tue, 9 Sep 2025 01:37:21 +0900 Subject: [PATCH 91/93] =?UTF-8?q?[fix]=20=EC=98=A4=ED=83=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/application/service/handler/PostHandler.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/konkuk/thip/post/application/service/handler/PostHandler.java b/src/main/java/konkuk/thip/post/application/service/handler/PostHandler.java index 7460bc210..df798c5df 100644 --- a/src/main/java/konkuk/thip/post/application/service/handler/PostHandler.java +++ b/src/main/java/konkuk/thip/post/application/service/handler/PostHandler.java @@ -21,7 +21,7 @@ public class PostHandler { private final RecordCommandPort recordCommandPort; private final VoteCommandPort voteCommandPort; - private final PostQueryPort portQueryPort; + private final PostQueryPort postQueryPort; public CountUpdatable findPost(PostType type, Long postId) { return switch (type) { @@ -41,9 +41,9 @@ public void updatePost(PostType type, CountUpdatable post) { public PostQueryDto getPostQueryDto(PostType type, Long postId) { return switch (type) { - case FEED -> portQueryPort.getPostQueryDtoByFeedId(postId); - case RECORD -> portQueryPort.getPostQueryDtoByRecordId(postId); - case VOTE -> portQueryPort.getPostQueryDtoByVoteId(postId); + case FEED -> postQueryPort.getPostQueryDtoByFeedId(postId); + case RECORD -> postQueryPort.getPostQueryDtoByRecordId(postId); + case VOTE -> postQueryPort.getPostQueryDtoByVoteId(postId); }; } } From 39a96c7d9dff349f456a5e2bfe31751f0818d5b7 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Tue, 9 Sep 2025 02:12:47 +0900 Subject: [PATCH 92/93] =?UTF-8?q?[merge]=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=20=EC=9D=B4=EB=8F=99=ED=95=9C?= =?UTF-8?q?=EA=B1=B0=20=EB=B0=98=EC=98=81=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../out/persistence/FeedCommandPersistenceAdapter.java | 6 +++--- .../out/persistence/RecordCommandPersistenceAdapter.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/konkuk/thip/feed/adapter/out/persistence/FeedCommandPersistenceAdapter.java b/src/main/java/konkuk/thip/feed/adapter/out/persistence/FeedCommandPersistenceAdapter.java index 2f35a4a4f..58228d1ec 100644 --- a/src/main/java/konkuk/thip/feed/adapter/out/persistence/FeedCommandPersistenceAdapter.java +++ b/src/main/java/konkuk/thip/feed/adapter/out/persistence/FeedCommandPersistenceAdapter.java @@ -5,14 +5,14 @@ import konkuk.thip.comment.adapter.out.persistence.repository.CommentJpaRepository; import konkuk.thip.comment.adapter.out.persistence.repository.CommentLikeJpaRepository; import konkuk.thip.common.exception.EntityNotFoundException; -import konkuk.thip.feed.adapter.out.jpa.*; +import konkuk.thip.feed.adapter.out.jpa.FeedJpaEntity; +import konkuk.thip.feed.adapter.out.jpa.SavedFeedJpaEntity; import konkuk.thip.feed.adapter.out.mapper.FeedMapper; import konkuk.thip.feed.adapter.out.persistence.repository.FeedJpaRepository; import konkuk.thip.feed.adapter.out.persistence.repository.SavedFeedJpaRepository; import konkuk.thip.feed.application.port.out.FeedCommandPort; import konkuk.thip.feed.domain.Feed; -import konkuk.thip.post.application.port.out.dto.PostQueryDto; -import konkuk.thip.post.adapter.out.persistence.PostLikeJpaRepository; +import konkuk.thip.post.adapter.out.persistence.repository.PostLikeJpaRepository; import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/konkuk/thip/roompost/adapter/out/persistence/RecordCommandPersistenceAdapter.java b/src/main/java/konkuk/thip/roompost/adapter/out/persistence/RecordCommandPersistenceAdapter.java index 905bb6c4a..8d6351fb3 100644 --- a/src/main/java/konkuk/thip/roompost/adapter/out/persistence/RecordCommandPersistenceAdapter.java +++ b/src/main/java/konkuk/thip/roompost/adapter/out/persistence/RecordCommandPersistenceAdapter.java @@ -3,9 +3,9 @@ import konkuk.thip.comment.adapter.out.persistence.repository.CommentJpaRepository; import konkuk.thip.comment.adapter.out.persistence.repository.CommentLikeJpaRepository; import konkuk.thip.common.exception.EntityNotFoundException; +import konkuk.thip.post.adapter.out.persistence.repository.PostLikeJpaRepository; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; -import konkuk.thip.post.adapter.out.persistence.PostLikeJpaRepository; import konkuk.thip.roompost.adapter.out.jpa.RecordJpaEntity; import konkuk.thip.roompost.adapter.out.mapper.RecordMapper; import konkuk.thip.roompost.adapter.out.persistence.repository.record.RecordJpaRepository; From 50b947adcb8e5df9b46e2abc3dc40f7511d9e2e9 Mon Sep 17 00:00:00 2001 From: janghyunjun Date: Tue, 9 Sep 2025 02:17:14 +0900 Subject: [PATCH 93/93] =?UTF-8?q?[merge]=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=20=EC=9D=B4=EB=8F=99=ED=95=9C?= =?UTF-8?q?=EA=B1=B0=20=EB=B0=98=EC=98=81=20(#289)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../out/persistence/VoteCommandPersistenceAdapter.java | 6 +++--- .../konkuk/thip/common/util/TestEntityFactory.java | 2 +- .../thip/user/adapter/in/web/UserDeleteApiTest.java | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/konkuk/thip/roompost/adapter/out/persistence/VoteCommandPersistenceAdapter.java b/src/main/java/konkuk/thip/roompost/adapter/out/persistence/VoteCommandPersistenceAdapter.java index 8db4e64ae..b74daa966 100644 --- a/src/main/java/konkuk/thip/roompost/adapter/out/persistence/VoteCommandPersistenceAdapter.java +++ b/src/main/java/konkuk/thip/roompost/adapter/out/persistence/VoteCommandPersistenceAdapter.java @@ -3,11 +3,9 @@ import konkuk.thip.comment.adapter.out.persistence.repository.CommentJpaRepository; import konkuk.thip.comment.adapter.out.persistence.repository.CommentLikeJpaRepository; import konkuk.thip.common.exception.EntityNotFoundException; -import konkuk.thip.post.adapter.out.persistence.PostLikeJpaRepository; +import konkuk.thip.post.adapter.out.persistence.repository.PostLikeJpaRepository; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; -import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; -import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import konkuk.thip.roompost.adapter.out.jpa.VoteItemJpaEntity; import konkuk.thip.roompost.adapter.out.jpa.VoteJpaEntity; import konkuk.thip.roompost.adapter.out.jpa.VoteParticipantJpaEntity; @@ -21,6 +19,8 @@ import konkuk.thip.roompost.domain.Vote; import konkuk.thip.roompost.domain.VoteItem; import konkuk.thip.roompost.domain.VoteParticipant; +import konkuk.thip.user.adapter.out.jpa.UserJpaEntity; +import konkuk.thip.user.adapter.out.persistence.repository.UserJpaRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; diff --git a/src/test/java/konkuk/thip/common/util/TestEntityFactory.java b/src/test/java/konkuk/thip/common/util/TestEntityFactory.java index 51733a0ee..27fb9b62a 100644 --- a/src/test/java/konkuk/thip/common/util/TestEntityFactory.java +++ b/src/test/java/konkuk/thip/common/util/TestEntityFactory.java @@ -13,7 +13,7 @@ import konkuk.thip.post.adapter.out.jpa.PostLikeJpaEntity; import konkuk.thip.post.domain.PostType; import konkuk.thip.recentSearch.adapter.out.jpa.RecentSearchJpaEntity; -import konkuk.thip.recentSearch.adapter.out.jpa.RecentSearchType; +import konkuk.thip.recentSearch.domain.value.RecentSearchType; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.adapter.out.jpa.RoomParticipantJpaEntity; import konkuk.thip.room.domain.value.RoomParticipantRole; diff --git a/src/test/java/konkuk/thip/user/adapter/in/web/UserDeleteApiTest.java b/src/test/java/konkuk/thip/user/adapter/in/web/UserDeleteApiTest.java index f3e66fe8c..0a513adcd 100644 --- a/src/test/java/konkuk/thip/user/adapter/in/web/UserDeleteApiTest.java +++ b/src/test/java/konkuk/thip/user/adapter/in/web/UserDeleteApiTest.java @@ -14,14 +14,14 @@ import konkuk.thip.feed.adapter.out.persistence.repository.FeedJpaRepository; import konkuk.thip.feed.adapter.out.persistence.repository.SavedFeedJpaRepository; import konkuk.thip.post.adapter.out.jpa.PostLikeJpaEntity; -import konkuk.thip.post.adapter.out.persistence.PostLikeJpaRepository; +import konkuk.thip.post.adapter.out.persistence.repository.PostLikeJpaRepository; import konkuk.thip.recentSearch.adapter.out.persistence.repository.RecentSearchJpaRepository; import konkuk.thip.room.adapter.out.jpa.RoomJpaEntity; import konkuk.thip.room.adapter.out.jpa.RoomParticipantJpaEntity; -import konkuk.thip.room.adapter.out.jpa.RoomStatus; import konkuk.thip.room.adapter.out.persistence.repository.RoomJpaRepository; import konkuk.thip.room.adapter.out.persistence.repository.roomparticipant.RoomParticipantJpaRepository; import konkuk.thip.room.domain.value.Category; +import konkuk.thip.room.domain.value.RoomStatus; import konkuk.thip.roompost.adapter.out.jpa.*; import konkuk.thip.roompost.adapter.out.persistence.repository.attendancecheck.AttendanceCheckJpaRepository; import konkuk.thip.roompost.adapter.out.persistence.repository.record.RecordJpaRepository; @@ -49,9 +49,9 @@ import static konkuk.thip.common.entity.StatusType.INACTIVE; import static konkuk.thip.common.exception.code.ErrorCode.USER_CANNOT_DELETE_ROOM_HOST; import static konkuk.thip.post.domain.PostType.*; -import static konkuk.thip.room.adapter.out.jpa.RoomParticipantRole.HOST; -import static konkuk.thip.room.adapter.out.jpa.RoomParticipantRole.MEMBER; -import static konkuk.thip.room.adapter.out.jpa.RoomStatus.*; +import static konkuk.thip.room.domain.value.RoomParticipantRole.HOST; +import static konkuk.thip.room.domain.value.RoomParticipantRole.MEMBER; +import static konkuk.thip.room.domain.value.RoomStatus.*; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue;