diff --git a/src/main/java/com/example/RealMatch/business/application/event/CampaignProposalStatusChangedEvent.java b/src/main/java/com/example/RealMatch/business/application/event/CampaignProposalStatusChangedEvent.java index 2126e86f..08de80f7 100644 --- a/src/main/java/com/example/RealMatch/business/application/event/CampaignProposalStatusChangedEvent.java +++ b/src/main/java/com/example/RealMatch/business/application/event/CampaignProposalStatusChangedEvent.java @@ -1,5 +1,6 @@ package com.example.RealMatch.business.application.event; +import com.example.RealMatch.business.domain.enums.ProposalDirection; import com.example.RealMatch.business.domain.enums.ProposalStatus; /** @@ -11,6 +12,7 @@ public record CampaignProposalStatusChangedEvent( Long brandUserId, Long creatorUserId, ProposalStatus newStatus, - Long actorUserId // 상태 변경을 수행한 사용자 ID (수락/거절한 사용자) + Long actorUserId, // 상태 변경을 수행한 사용자 ID (수락/거절한 사용자) + ProposalDirection proposalDirection // 누가 제안했는지 방향 (BRAND_TO_CREATOR / CREATOR_TO_BRAND) ) { } diff --git a/src/main/java/com/example/RealMatch/business/application/service/CampaignProposalService.java b/src/main/java/com/example/RealMatch/business/application/service/CampaignProposalService.java index 10121b96..c3362ac3 100644 --- a/src/main/java/com/example/RealMatch/business/application/service/CampaignProposalService.java +++ b/src/main/java/com/example/RealMatch/business/application/service/CampaignProposalService.java @@ -359,7 +359,8 @@ private void publishProposalStatusChangedEvent(CampaignProposal proposal, Propos brandUserId, creatorUserId, newStatus, - actorUserId + actorUserId, + ProposalDirection.fromWhoProposed(proposal.getWhoProposed()) ); eventPublisher.publishEvent(event); } diff --git a/src/main/java/com/example/RealMatch/campaign/domain/repository/CampaignRepository.java b/src/main/java/com/example/RealMatch/campaign/domain/repository/CampaignRepository.java index dd31ecfd..025871a1 100644 --- a/src/main/java/com/example/RealMatch/campaign/domain/repository/CampaignRepository.java +++ b/src/main/java/com/example/RealMatch/campaign/domain/repository/CampaignRepository.java @@ -16,6 +16,9 @@ public interface CampaignRepository extends JpaRepository { Optional findById(Long id); + @Query("SELECT c FROM Campaign c WHERE c.id = :id AND c.isDeleted = false") + Optional findByIdAndIsDeletedFalse(@Param("id") Long id); + List findAll(); List findByCreatedBy(Long createdBy); diff --git a/src/main/java/com/example/RealMatch/chat/application/event/proposal/CampaignProposalStatusChangedEventListener.java b/src/main/java/com/example/RealMatch/chat/application/event/proposal/CampaignProposalStatusChangedEventListener.java index b41333b1..fe391786 100644 --- a/src/main/java/com/example/RealMatch/chat/application/event/proposal/CampaignProposalStatusChangedEventListener.java +++ b/src/main/java/com/example/RealMatch/chat/application/event/proposal/CampaignProposalStatusChangedEventListener.java @@ -8,7 +8,9 @@ import org.springframework.transaction.event.TransactionalEventListener; import com.example.RealMatch.business.application.event.CampaignProposalStatusChangedEvent; +import com.example.RealMatch.business.domain.enums.ProposalDirection; import com.example.RealMatch.business.domain.enums.ProposalStatus; +import com.example.RealMatch.chat.domain.enums.ChatProposalDirection; import com.example.RealMatch.chat.domain.enums.ChatProposalStatus; import lombok.RequiredArgsConstructor; @@ -36,6 +38,7 @@ public void handleCampaignProposalStatusChanged(CampaignProposalStatusChangedEve event.proposalId(), event.newStatus()); ChatProposalStatus chatStatus = toChatProposalStatus(event.newStatus()); + ChatProposalDirection direction = toChatProposalDirection(event.proposalDirection()); String eventId = ProposalStatusChangedEvent.generateEventId(event.proposalId(), chatStatus); ProposalStatusChangedEvent chatEvent = new ProposalStatusChangedEvent( @@ -45,7 +48,8 @@ public void handleCampaignProposalStatusChanged(CampaignProposalStatusChangedEve event.brandUserId(), event.creatorUserId(), chatStatus, - event.actorUserId() + event.actorUserId(), + direction ); eventPublisher.publishEvent(chatEvent); @@ -65,4 +69,14 @@ private static ChatProposalStatus toChatProposalStatus(ProposalStatus status) { case REJECTED -> ChatProposalStatus.REJECTED; }; } + + private static ChatProposalDirection toChatProposalDirection(ProposalDirection direction) { + if (direction == null) { + return ChatProposalDirection.NONE; + } + return switch (direction) { + case BRAND_TO_CREATOR -> ChatProposalDirection.BRAND_TO_CREATOR; + case CREATOR_TO_BRAND -> ChatProposalDirection.CREATOR_TO_BRAND; + }; + } } diff --git a/src/main/java/com/example/RealMatch/chat/application/event/proposal/ProposalStatusChangedEvent.java b/src/main/java/com/example/RealMatch/chat/application/event/proposal/ProposalStatusChangedEvent.java index 76b15f1e..63fb891e 100644 --- a/src/main/java/com/example/RealMatch/chat/application/event/proposal/ProposalStatusChangedEvent.java +++ b/src/main/java/com/example/RealMatch/chat/application/event/proposal/ProposalStatusChangedEvent.java @@ -1,9 +1,10 @@ package com.example.RealMatch.chat.application.event.proposal; +import com.example.RealMatch.chat.domain.enums.ChatProposalDirection; import com.example.RealMatch.chat.domain.enums.ChatProposalStatus; /** - * 채팅 모듈 내부용 제안 상태 변경 이벤트. + * 채팅 모듈 내부용 제안 상태 변경 이벤트 * 비즈니스 이벤트(CampaignProposalStatusChangedEvent)를 변환한 결과물입니다. */ public record ProposalStatusChangedEvent( @@ -13,7 +14,8 @@ public record ProposalStatusChangedEvent( Long brandUserId, Long creatorUserId, ChatProposalStatus newStatus, - Long actorUserId // 상태 변경을 수행한 사용자 ID (수락/거절/취소한 사용자) + Long actorUserId, // 상태 변경을 수행한 사용자 ID (수락/거절/취소한 사용자) + ChatProposalDirection proposalDirection ) { /** * 같은 proposalId와 newStatus 조합이면 항상 같은 ID가 생성됩니다. diff --git a/src/main/java/com/example/RealMatch/chat/application/event/proposal/ProposalSystemMessageHandler.java b/src/main/java/com/example/RealMatch/chat/application/event/proposal/ProposalSystemMessageHandler.java index 9d8bca89..9c57e395 100644 --- a/src/main/java/com/example/RealMatch/chat/application/event/proposal/ProposalSystemMessageHandler.java +++ b/src/main/java/com/example/RealMatch/chat/application/event/proposal/ProposalSystemMessageHandler.java @@ -194,7 +194,7 @@ public void handleProposalStatusChanged(ProposalStatusChangedEvent event) { ); // 매칭 완료 시 추가 카드 전송 - if (event.newStatus() == ChatProposalStatus.MATCHED) { + if (event.newStatus() == ChatProposalStatus.MATCHED && event.campaignId() != null) { String matchedCardKey = String.format("%s:MATCHED_CARD", event.eventId()); SystemEventMeta matchedMeta = new SystemEventMeta( @@ -210,18 +210,17 @@ public void handleProposalStatusChanged(ProposalStatusChangedEvent event) { matchedContextData.put("domainId", event.proposalId()); matchedContextData.put("proposalId", event.proposalId()); } - if (event.campaignId() != null) { - matchedContextData.put("campaignId", event.campaignId()); - } + matchedContextData.put("campaignId", event.campaignId()); + Long campaignId = event.campaignId(); execute( matchedMeta, matchedContextData, - () -> matchedCampaignPayloadProvider.getPayload(event.campaignId()) + () -> matchedCampaignPayloadProvider.getPayload(campaignId, event.proposalDirection()) .orElseThrow(() -> { String message = String.format( - "Failed to get matched campaign payload. campaignId=%d may not exist or be deleted", - event.campaignId() + "Failed to get matched campaign payload. campaignId=%s may not exist or be deleted", + campaignId ); LOG.warn("[Proposal] {}. eventId={}, roomId={}", message, event.eventId(), roomId); return new IllegalStateException(message); diff --git a/src/main/java/com/example/RealMatch/chat/application/service/room/MatchedCampaignPayloadProvider.java b/src/main/java/com/example/RealMatch/chat/application/service/room/MatchedCampaignPayloadProvider.java index 4db2979d..d1bf9c05 100644 --- a/src/main/java/com/example/RealMatch/chat/application/service/room/MatchedCampaignPayloadProvider.java +++ b/src/main/java/com/example/RealMatch/chat/application/service/room/MatchedCampaignPayloadProvider.java @@ -2,9 +2,10 @@ import java.util.Optional; +import com.example.RealMatch.chat.domain.enums.ChatProposalDirection; import com.example.RealMatch.chat.presentation.dto.response.ChatMatchedCampaignPayloadResponse; public interface MatchedCampaignPayloadProvider { - Optional getPayload(Long campaignId); + Optional getPayload(Long campaignId, ChatProposalDirection proposalDirection); } diff --git a/src/main/java/com/example/RealMatch/chat/application/service/room/MatchedCampaignPayloadProviderImpl.java b/src/main/java/com/example/RealMatch/chat/application/service/room/MatchedCampaignPayloadProviderImpl.java index 2d625e55..e17a22df 100644 --- a/src/main/java/com/example/RealMatch/chat/application/service/room/MatchedCampaignPayloadProviderImpl.java +++ b/src/main/java/com/example/RealMatch/chat/application/service/room/MatchedCampaignPayloadProviderImpl.java @@ -6,6 +6,7 @@ import com.example.RealMatch.campaign.domain.entity.Campaign; import com.example.RealMatch.campaign.domain.repository.CampaignRepository; +import com.example.RealMatch.chat.domain.enums.ChatProposalDirection; import com.example.RealMatch.chat.presentation.dto.response.ChatMatchedCampaignPayloadResponse; import lombok.RequiredArgsConstructor; @@ -19,16 +20,15 @@ public class MatchedCampaignPayloadProviderImpl implements MatchedCampaignPayloa private final CampaignRepository campaignRepository; @Override - public Optional getPayload(Long campaignId) { + public Optional getPayload(Long campaignId, ChatProposalDirection proposalDirection) { if (campaignId == null) { return Optional.empty(); } - return campaignRepository.findById(campaignId) - .filter(c -> !c.isDeleted()) - .map(this::toPayload); + return campaignRepository.findByIdAndIsDeletedFalse(campaignId) + .map(c -> toPayload(c, proposalDirection)); } - private ChatMatchedCampaignPayloadResponse toPayload(Campaign campaign) { + private ChatMatchedCampaignPayloadResponse toPayload(Campaign campaign, ChatProposalDirection proposalDirection) { // TODO: orderNumber - 결제/주문 도메인에서 주문 번호 확정 시 채팅으로 전달하거나, // ProposalStatusChangedEvent(또는 매칭 완료 이벤트)에 orderNumber 포함 후 여기서 사용 return new ChatMatchedCampaignPayloadResponse( @@ -37,7 +37,8 @@ private ChatMatchedCampaignPayloadResponse toPayload(Campaign campaign) { campaign.getRewardAmount() != null ? campaign.getRewardAmount() : 0L, DEFAULT_CURRENCY, "", - null + null, + proposalDirection ); } } diff --git a/src/main/java/com/example/RealMatch/chat/presentation/dto/response/ChatMatchedCampaignPayloadResponse.java b/src/main/java/com/example/RealMatch/chat/presentation/dto/response/ChatMatchedCampaignPayloadResponse.java index ea2e6cf1..6c64685b 100644 --- a/src/main/java/com/example/RealMatch/chat/presentation/dto/response/ChatMatchedCampaignPayloadResponse.java +++ b/src/main/java/com/example/RealMatch/chat/presentation/dto/response/ChatMatchedCampaignPayloadResponse.java @@ -1,11 +1,14 @@ package com.example.RealMatch.chat.presentation.dto.response; +import com.example.RealMatch.chat.domain.enums.ChatProposalDirection; + public record ChatMatchedCampaignPayloadResponse( Long campaignId, String campaignName, long amount, String currency, String orderNumber, - String message + String message, + ChatProposalDirection proposalDirection ) implements ChatSystemMessagePayload { }