From 45acf73a4adfab82cdafc1023dabaf201cc1ad49 Mon Sep 17 00:00:00 2001 From: Abdalhamid Alhamad Date: Mon, 12 Jan 2026 16:47:28 +0300 Subject: [PATCH] feat: enhance transaction notification logging and error handling - Added console logging for emitted transaction creation events in TransactionService. - Improved error handling in TransactionNotificationListener for i18n translation failures, providing fallback messages. - Updated amount parsing in MoneyRequestNotificationListener to ensure consistent handling of string and numeric values. --- src/card/services/transaction.service.ts | 3 + .../money-request-notification.listener.ts | 6 +- .../transaction-notification.listener.ts | 121 ++++++++++++------ 3 files changed, 85 insertions(+), 45 deletions(-) diff --git a/src/card/services/transaction.service.ts b/src/card/services/transaction.service.ts index 00a910f..e94ac64 100644 --- a/src/card/services/transaction.service.ts +++ b/src/card/services/transaction.service.ts @@ -117,7 +117,10 @@ export class TransactionService { isChildSpending: true, timestamp: new Date(), }; + + console.log(`[TransactionService] Emitting TRANSACTION_CREATED event for transaction ${transaction.id}`); this.eventEmitter.emit(NOTIFICATION_EVENTS.TRANSACTION_CREATED, event); + console.log(`[TransactionService] Event emitted successfully`); return transaction; } diff --git a/src/common/modules/notification/listeners/money-request-notification.listener.ts b/src/common/modules/notification/listeners/money-request-notification.listener.ts index 20587b9..cc6359f 100644 --- a/src/common/modules/notification/listeners/money-request-notification.listener.ts +++ b/src/common/modules/notification/listeners/money-request-notification.listener.ts @@ -128,7 +128,7 @@ export class MoneyRequestNotificationListener { const child = moneyRequest?.junior; const childUser = child?.customer?.user; const childName = childUser?.firstName || 'Your child'; - const amount = moneyRequest.amount; + const amount = typeof moneyRequest.amount === 'string' ? parseFloat(moneyRequest.amount) : moneyRequest.amount; const reason = moneyRequest.reason || 'No reason provided'; this.logger.debug( @@ -175,7 +175,7 @@ export class MoneyRequestNotificationListener { return; } - const amount = moneyRequest.amount; + const amount = typeof moneyRequest.amount === 'string' ? parseFloat(moneyRequest.amount) : moneyRequest.amount; this.logger.debug( `Notifying child (user ${childUser.id}): Money request of $${amount} was approved` @@ -218,7 +218,7 @@ export class MoneyRequestNotificationListener { return; } - const amount = moneyRequest.amount; + const amount = typeof moneyRequest.amount === 'string' ? parseFloat(moneyRequest.amount) : moneyRequest.amount; const reason = rejectionReason || 'No reason provided'; this.logger.debug( diff --git a/src/common/modules/notification/listeners/transaction-notification.listener.ts b/src/common/modules/notification/listeners/transaction-notification.listener.ts index 51924b8..4691316 100644 --- a/src/common/modules/notification/listeners/transaction-notification.listener.ts +++ b/src/common/modules/notification/listeners/transaction-notification.listener.ts @@ -41,12 +41,15 @@ export class TransactionNotificationListener { @OnEvent(NOTIFICATION_EVENTS.TRANSACTION_CREATED) async handleTransactionCreated(event: ITransactionCreatedEvent): Promise { try { + console.log(`[TransactionNotificationListener] Event received: ${NOTIFICATION_EVENTS.TRANSACTION_CREATED}`); const { transaction, card, isTopUp, isChildSpending } = event; this.logger.log( `Processing transaction notification for transaction ${transaction.id} - ` + `isTopUp: ${isTopUp}, isChildSpending: ${isChildSpending}` ); + + console.log(`[TransactionNotificationListener] Transaction: ${transaction.id}, Card: ${card?.id}, isTopUp: ${isTopUp}, isChildSpending: ${isChildSpending}`); await this.notifyTransactionOwner(transaction, card, isTopUp, isChildSpending); @@ -62,6 +65,7 @@ export class TransactionNotificationListener { `Transaction notification processed successfully for transaction ${transaction.id}` ); } catch (error: any) { + console.error(`[TransactionNotificationListener] ERROR:`, error); this.logger.error( `Failed to process transaction notification: ${error?.message || 'Unknown error'}`, error?.stack @@ -96,28 +100,41 @@ export class TransactionNotificationListener { const balance = card.account?.balance || 0; const currency = card.account?.currency || transaction.transactionCurrency || 'SAR'; - const title = isTopUp - ? this.i18n.t('app.NOTIFICATION.CHILD_TOP_UP_TITLE', { lang: locale }) - : this.i18n.t('app.NOTIFICATION.CHILD_SPENDING_TITLE', { lang: locale }); + let title: string; + let message: string; + + try { + title = isTopUp + ? this.i18n.t('app.NOTIFICATION.CHILD_TOP_UP_TITLE', { lang: locale }) + : this.i18n.t('app.NOTIFICATION.CHILD_SPENDING_TITLE', { lang: locale }); - const message = isTopUp - ? this.i18n.t('app.NOTIFICATION.CHILD_TOP_UP_MESSAGE', { - lang: locale, - args: { - amount: amount.toString(), - currency: currency, - balance: balance.toString(), - }, - }) - : this.i18n.t('app.NOTIFICATION.CHILD_SPENDING_MESSAGE', { - lang: locale, - args: { - amount: amount.toString(), - currency: currency, - merchant: merchant, - balance: balance.toString(), - }, - }); + message = isTopUp + ? this.i18n.t('app.NOTIFICATION.CHILD_TOP_UP_MESSAGE', { + lang: locale, + args: { + amount: amount.toString(), + currency: currency, + balance: balance.toString(), + }, + }) + : this.i18n.t('app.NOTIFICATION.CHILD_SPENDING_MESSAGE', { + lang: locale, + args: { + amount: amount.toString(), + currency: currency, + merchant: merchant, + balance: balance.toString(), + }, + }); + } catch (i18nError: any) { + console.error(`[TransactionNotificationListener] i18n error:`, i18nError); + this.logger.error(`i18n translation failed: ${i18nError?.message}`, i18nError?.stack); + // Fallback to English without i18n + title = isTopUp ? 'Card Topped Up' : 'Purchase Successful'; + message = isTopUp + ? `You received ${amount} ${currency}. Total balance: ${balance} ${currency}` + : `You spent ${amount} ${currency} at ${merchant}. Balance: ${balance} ${currency}`; + } this.logger.debug( `Notifying transaction owner (user ${user.id}) - Amount: ${amount} ${currency}, Merchant: ${merchant}` @@ -180,17 +197,27 @@ export class TransactionNotificationListener { `Notifying parent (user ${parentUser.id}): ${childName} spent ${amount} ${currency} at ${merchant}` ); - const title = this.i18n.t('app.NOTIFICATION.PARENT_SPENDING_TITLE', { lang: locale }); - const message = this.i18n.t('app.NOTIFICATION.PARENT_SPENDING_MESSAGE', { - lang: locale, - args: { - childName: childName, - amount: amount.toString(), - currency: currency, - merchant: merchant, - balance: balance.toString(), - }, - }); + let title: string; + let message: string; + + try { + title = this.i18n.t('app.NOTIFICATION.PARENT_SPENDING_TITLE', { lang: locale }); + message = this.i18n.t('app.NOTIFICATION.PARENT_SPENDING_MESSAGE', { + lang: locale, + args: { + childName: childName, + amount: amount.toString(), + currency: currency, + merchant: merchant, + balance: balance.toString(), + }, + }); + } catch (i18nError: any) { + console.error(`[TransactionNotificationListener] i18n error in parent spending:`, i18nError); + this.logger.error(`i18n translation failed: ${i18nError?.message}`, i18nError?.stack); + title = 'Child Spending Alert'; + message = `${childName} spent ${amount} ${currency} at ${merchant}. Balance: ${balance} ${currency}`; + } await this.notificationFactory.send({ userId: parentUser.id, @@ -250,16 +277,26 @@ export class TransactionNotificationListener { `Notifying parent (user ${parentUser.id}): Transferred ${amount} ${currency} to ${childName}` ); - const title = this.i18n.t('app.NOTIFICATION.PARENT_TOP_UP_TITLE', { lang: locale }); - const message = this.i18n.t('app.NOTIFICATION.PARENT_TOP_UP_MESSAGE', { - lang: locale, - args: { - amount: amount.toString(), - currency: currency, - childName: childName, - balance: balance.toString(), - }, - }); + let title: string; + let message: string; + + try { + title = this.i18n.t('app.NOTIFICATION.PARENT_TOP_UP_TITLE', { lang: locale }); + message = this.i18n.t('app.NOTIFICATION.PARENT_TOP_UP_MESSAGE', { + lang: locale, + args: { + amount: amount.toString(), + currency: currency, + childName: childName, + balance: balance.toString(), + }, + }); + } catch (i18nError: any) { + console.error(`[TransactionNotificationListener] i18n error in parent top-up:`, i18nError); + this.logger.error(`i18n translation failed: ${i18nError?.message}`, i18nError?.stack); + title = 'Top-Up Confirmation'; + message = `You transferred ${amount} ${currency} to ${childName}. Balance: ${balance} ${currency}`; + } await this.notificationFactory.send({ userId: parentUser.id,