diff --git a/firebase.json b/firebase.json index b588d0764..6022aeb96 100644 --- a/firebase.json +++ b/firebase.json @@ -7,8 +7,6 @@ { "source": "functions", "codebase": "default", - "timeoutSeconds": 300, - "runtime": "nodejs18", "ignore": [ "node_modules", ".git", diff --git a/functions/package.json b/functions/package.json index 78edeea45..d7c7a0d1b 100644 --- a/functions/package.json +++ b/functions/package.json @@ -17,7 +17,8 @@ "main": "lib/index.js", "dependencies": { "firebase-admin": "^12.6.0", - "firebase-functions": "^6.0.1" + "firebase-functions": "^6.1.1", + "lodash": "^4.17.21" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^5.12.0", diff --git a/functions/src/notifications_service/notifications_service.ts b/functions/src/notifications_service/notifications_service.ts index 4b6f7f233..ca33ba5c5 100644 --- a/functions/src/notifications_service/notifications_service.ts +++ b/functions/src/notifications_service/notifications_service.ts @@ -6,7 +6,7 @@ import * as admin from "firebase-admin"; import * as logger from "firebase-functions/logger"; import messages from '../locales/en.json'; -// Initialize Firebase app in users_service.ts to ensure it's always available +// Initialize Firebase app if not already initialized if (admin.apps.length === 0) { try { admin.initializeApp(); @@ -130,42 +130,38 @@ function generateNotificationMessage(activityData: ActivityData) { return messages.expense_restored.replace("{expenseName}", expenseName).replace("{amountMessage}", amountMessage); case 'transaction_added': - if (paymentReason != null && paymentReason.trim().length > 0) { - return messages.transaction_added_with_reason.replace("{payerName}", payerName).replace("{receiverName}", receiverName).replace("{amountMessage}", formatCurrency(Math.abs(amount))).replace("{paymentReason}", paymentReason); - } else { - return messages.transaction_added.replace("{payerName}", payerName).replace("{receiverName}", receiverName).replace("{amountMessage}", formatCurrency(Math.abs(amount))); - } + return getTransactionMessage("transaction_added_with_reason", "transaction_added", payerName, receiverName, amount, paymentReason); case 'transaction_updated': - if (paymentReason != null && paymentReason.trim().length > 0) { - return messages.transaction_updated_with_reason.replace("{payerName}", payerName).replace("{receiverName}", receiverName).replace("{amountMessage}", formatCurrency(Math.abs(amount))).replace("{paymentReason}", paymentReason); - } else { - return messages.transaction_updated.replace("{payerName}", payerName).replace("{receiverName}", receiverName).replace("{amountMessage}", formatCurrency(Math.abs(amount))); - } + return getTransactionMessage("transaction_updated_with_reason", "transaction_updated", payerName, receiverName, amount, paymentReason); case 'transaction_deleted': - if (paymentReason != null && paymentReason.trim().length > 0) { - return messages.transaction_deleted_with_reason.replace("{payerName}", payerName).replace("{receiverName}", receiverName).replace("{amountMessage}", formatCurrency(Math.abs(amount))).replace("{paymentReason}", paymentReason); - } else { - return messages.transaction_deleted.replace("{payerName}", payerName).replace("{receiverName}", receiverName).replace("{amountMessage}", formatCurrency(Math.abs(amount))); - } + return getTransactionMessage("transaction_deleted_with_reason", "transaction_deleted", payerName, receiverName, amount, paymentReason); case 'transaction_restored': - if (paymentReason != null && paymentReason.trim().length > 0) { - return messages.transaction_restored_with_reason.replace("{payerName}", payerName).replace("{receiverName}", receiverName).replace("{amountMessage}", formatCurrency(Math.abs(amount))).replace("{paymentReason}", paymentReason); - } else { - return messages.transaction_restored.replace("{payerName}", payerName).replace("{receiverName}", receiverName).replace("{amountMessage}", formatCurrency(Math.abs(amount))); - } + return getTransactionMessage("transaction_restored_with_reason", "transaction_restored", payerName, receiverName, amount, paymentReason); default: return messages.new_activity; } } -function capitalizeFirstLetter(name: string): string { - if (!name) return ''; - return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase(); -} +type MessageKeys = keyof typeof messages; +function getTransactionMessage( + messageKeyWithReason: MessageKeys, + messageKeyWithoutReason: MessageKeys, + payerName: string, + receiverName: string, + amount: number, + paymentReason?: string, +): string { + const messageKey = paymentReason?.trim() ? messageKeyWithReason : messageKeyWithoutReason; + return messages[messageKey] + .replace("{payerName}", payerName) + .replace("{receiverName}", receiverName) + .replace("{amountMessage}", formatCurrency(Math.abs(amount))) + .replace("{paymentReason}", paymentReason || ""); +}; // Helper function to generate notification amount message based on owedAmount function generateAmountMessage(owedAmount: number): string { @@ -178,6 +174,11 @@ function generateAmountMessage(owedAmount: number): string { } } +function capitalizeFirstLetter(name: string): string { + if (!name) return ''; + return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase(); +} + // Function to send notification using FCM with retry mechanism async function sendNotification(userId: string, title: string, body: string, activityId: string, maxRetries = 5) { const baseDelay = 1000; // Initial delay in milliseconds diff --git a/functions/src/users_service/users_service.ts b/functions/src/users_service/users_service.ts index 1a9a74e9c..587d23e34 100644 --- a/functions/src/users_service/users_service.ts +++ b/functions/src/users_service/users_service.ts @@ -3,8 +3,9 @@ import * as admin from 'firebase-admin'; import { onDocumentWritten } from 'firebase-functions/v2/firestore'; import * as logger from 'firebase-functions/logger'; +import * as _ from 'lodash'; -// Initialize Firebase app in users_service.ts to ensure it's always available +// Initialize Firebase app if not already initialized if (admin.apps.length === 0) { try { admin.initializeApp(); @@ -43,7 +44,8 @@ export const onGroupWrite = onDocumentWritten( } // Check if balances field changed - if (beforeData.balances != afterData.balances) { + if (!_.isEqual(beforeData.balances, afterData.balances)) { + const olderBalances = beforeData.balances || []; const updatedBalances = afterData.balances || []; diff --git a/functions/tsconfig.json b/functions/tsconfig.json index 5e03228f0..89539cc98 100644 --- a/functions/tsconfig.json +++ b/functions/tsconfig.json @@ -1,15 +1,12 @@ { "compilerOptions": { "module": "commonjs", - "moduleResolution": "node", "noImplicitReturns": true, "noUnusedLocals": true, "resolveJsonModule": true, "esModuleInterop": true, "outDir": "lib", "sourceMap": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, "strict": true, "target": "ES2020" }, @@ -18,7 +15,6 @@ "src" ], "exclude": [ - "node_modules", - "lib" + "node_modules" ] } diff --git a/package.json b/package.json index e008ac538..535428047 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,7 @@ { "dependencies": { "firebase-admin": "^13.0.1", - "firebase-functions": "^6.1.1" - }, - "devDependencies": { - "typescript": "^5.7.2" - }, - "scripts": { - "build": "tsc" + "firebase-functions": "^6.1.1", + "lodash": "^4.17.21" } }