feat(notifications): R2.8 residential WS events (TEC-2759)

- Add emitResidentialEvent helper on NotificationsGateway that fans
  residential:price-drop, residential:new-listing-in-project, and
  residential:inquiry-reply to the user's /notifications room.
- Wire three CQRS @EventsHandler listeners on ListingPriceChangedEvent
  (only when newPrice < oldPrice, match saved searches),
  ListingApprovedEvent (match saved searches with filters.projectId
  against property.projectDevelopmentId), and InquiryReadEvent
  (notify inquiry author).
- Redis pub/sub fan-out already handled by RedisIoAdapter from
  TEC-2766, so these broadcasts work across API instances.
- Unit tests for all three listeners and the new gateway helper.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Ho Ngoc Hai
2026-04-18 15:28:40 +07:00
parent 729afe2db6
commit 8c6e3b92d0
5 changed files with 511 additions and 0 deletions

View File

@@ -14,6 +14,11 @@ import { PaymentFailedListener } from './application/listeners/payment-failed.li
import { PaymentRefundedListener } from './application/listeners/payment-refunded.listener';
import { PhoneChangeRequestedListener } from './application/listeners/phone-change-requested.listener';
import { QuotaExceededListener } from './application/listeners/quota-exceeded.listener';
import {
ResidentialInquiryReplyListener,
ResidentialNewListingInProjectListener,
ResidentialPriceDropListener,
} from './application/listeners/residential-events.listener';
import { SubscriptionExpiredListener } from './application/listeners/subscription-expired.listener';
import { SubscriptionExpiringListener } from './application/listeners/subscription-expiring.listener';
import { SubscriptionRenewedListener } from './application/listeners/subscription-renewed.listener';
@@ -51,6 +56,9 @@ const EventListeners = [
UserKycUpdatedListener,
EmailChangeRequestedListener,
PhoneChangeRequestedListener,
ResidentialPriceDropListener,
ResidentialNewListingInProjectListener,
ResidentialInquiryReplyListener,
];
@Module({