22
33import com .backend .domain .bid .repository .BidRepository ;
44import com .backend .domain .notification .service .AuctionNotificationService ;
5+ import com .backend .domain .notification .service .BidNotificationService ;
56import com .backend .domain .product .entity .Product ;
67import com .backend .domain .product .enums .AuctionStatus ;
78import com .backend .domain .product .event .helper .ProductChangeTracker ;
@@ -26,6 +27,7 @@ public class AuctionSchedulerService {
2627 private final BidRepository bidRepository ;
2728 private final WebSocketService webSocketService ;
2829 private final AuctionNotificationService auctionNotificationService ;
30+ private final BidNotificationService bidNotificationService ;
2931 private final ApplicationEventPublisher eventPublisher ;
3032
3133 // 매분마다 실행되어 종료된 경매들을 확인하고 낙찰 처리
@@ -118,15 +120,18 @@ private void processAuctionEnd(Product product) {
118120 log .info ("상품 ID: {}, 낙찰가: {}원으로 낙찰 처리되었습니다." ,
119121 product .getId (), highestBidPrice );
120122
121- // 구독자들에게 낙찰 알림 전송
123+ // 구독자들에게 낙찰 알림 전송 (브로드캐스트)
122124 webSocketService .broadcastAuctionEnd (product .getId (), true , highestBidPrice );
123125
126+ // 개인 알림 전송
127+ sendAuctionEndNotifications (product , highestBidPrice );
128+
124129 } else {
125130 // 입찰이 없었던 경우 - 유찰 처리
126131 updateProduct (product , AuctionStatus .FAILED , null );
127132 log .info ("상품 ID: {}, 입찰이 없어 유찰 처리되었습니다." , product .getId ());
128133
129- // 구독자들에게 유찰 알림 전송
134+ // 구독자들에게 유찰 알림 전송 (브로드캐스트)
130135 webSocketService .broadcastAuctionEnd (product .getId (), false , 0L );
131136 }
132137
@@ -138,6 +143,42 @@ private void processAuctionEnd(Product product) {
138143 }
139144 }
140145
146+ // 경매 종료 시 개인 알림 전송
147+ private void sendAuctionEndNotifications (Product product , Long finalPrice ) {
148+ try {
149+ // 이 상품에 입찰한 모든 사람들 조회
150+ List <Object []> bidders = entityManager .createQuery (
151+ "SELECT b.member.id, b.bidPrice FROM Bid b WHERE b.product.id = :productId AND b.status = 'BIDDING' ORDER BY b.bidPrice DESC" ,
152+ Object [].class )
153+ .setParameter ("productId" , product .getId ())
154+ .getResultList ();
155+
156+ if (bidders .isEmpty ()) {
157+ return ;
158+ }
159+
160+ // 최고 입찰자 (낙찰자)
161+ Long winnerId = (Long ) bidders .get (0 )[0 ];
162+
163+ // 낙찰자에게 낙찰 알림
164+ bidNotificationService .notifyAuctionWon (winnerId , product , finalPrice );
165+
166+ // 나머지 입찰자들에게 낙찰 실패 알림
167+ for (int i = 1 ; i < bidders .size (); i ++) {
168+ Long loserId = (Long ) bidders .get (i )[0 ];
169+ Long loserBidPrice = ((Number ) bidders .get (i )[1 ]).longValue ();
170+ bidNotificationService .notifyAuctionLost (loserId , product , finalPrice , loserBidPrice );
171+ }
172+
173+ log .info ("상품 ID: {}에 대한 경매 종료 개인 알림 전송 완료. 낙찰자: {}, 탈락자: {}명" ,
174+ product .getId (), winnerId , bidders .size () - 1 );
175+
176+ } catch (Exception e ) {
177+ log .error ("경매 종료 개인 알림 전송 중 오류 발생. 상품 ID: {}, 오류: {}" ,
178+ product .getId (), e .getMessage (), e );
179+ }
180+ }
181+
141182 // 개별 경매 시작 처리
142183 private void processAuctionStart (Product product ) {
143184 try {
0 commit comments