From 2196a48ed2e32a435605631f262f34a9c680dd86 Mon Sep 17 00:00:00 2001
From: Antony Kithinzi <kithinzi97@gmail.com>
Date: Tue, 14 Nov 2023 00:26:27 +0300
Subject: [PATCH 01/14] ADD: Transaction Drafts Collection Key

---
 src/ONYXKEYS.ts | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts
index fa72a99b5fa2..c9e87cdb99fc 100755
--- a/src/ONYXKEYS.ts
+++ b/src/ONYXKEYS.ts
@@ -261,6 +261,9 @@ const ONYXKEYS = {
         REPORT_USER_IS_LEAVING_ROOM: 'reportUserIsLeavingRoom_',
         SECURITY_GROUP: 'securityGroup_',
         TRANSACTION: 'transactions_',
+
+        // Holds temporary transactions used during the creation and edit flow
+        TRANSACTION_DRAFT: 'transactionsDraft_',
         SPLIT_TRANSACTION_DRAFT: 'splitTransactionDraft_',
         PRIVATE_NOTES_DRAFT: 'privateNotesDraft_',
         NEXT_STEP: 'reportNextStep_',

From 1ebb2897f4bf2347845bd10c91d7c51d02fc0d64 Mon Sep 17 00:00:00 2001
From: Antony Kithinzi <kithinzi97@gmail.com>
Date: Tue, 14 Nov 2023 00:59:56 +0300
Subject: [PATCH 02/14] FIX: Changing transcation backup onyx collection to the
 transaction drafts onyx collection

---
 src/libs/actions/IOU.js              | 4 ++--
 src/libs/actions/TransactionEdit.js  | 6 +++---
 src/pages/EditRequestDistancePage.js | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js
index aa07f0e7ca34..8487a8a2b5c7 100644
--- a/src/libs/actions/IOU.js
+++ b/src/libs/actions/IOU.js
@@ -787,10 +787,10 @@ function updateDistanceRequest(transactionID, transactionThreadReportID, transac
     });
 
     if (_.has(transactionChanges, 'waypoints')) {
-        // Delete the backup transaction when editing waypoints when the server responds successfully and there are no errors
+        // Delete the draft transaction when editing waypoints when the server responds successfully and there are no errors
         successData.push({
             onyxMethod: Onyx.METHOD.SET,
-            key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}-backup`,
+            key: `${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`,
             value: null,
         });
     }
diff --git a/src/libs/actions/TransactionEdit.js b/src/libs/actions/TransactionEdit.js
index 78a271f0f8cd..2cb79ac387bd 100644
--- a/src/libs/actions/TransactionEdit.js
+++ b/src/libs/actions/TransactionEdit.js
@@ -11,7 +11,7 @@ function createBackupTransaction(transaction) {
         ...transaction,
     };
     // Use set so that it will always fully overwrite any backup transaction that could have existed before
-    Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}-backup`, newTransaction);
+    Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transaction.transactionID}`, newTransaction);
 }
 
 /**
@@ -19,12 +19,12 @@ function createBackupTransaction(transaction) {
  * @param {String} transactionID
  */
 function removeBackupTransaction(transactionID) {
-    Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}-backup`, null);
+    Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, null);
 }
 
 function restoreOriginalTransactionFromBackup(transactionID) {
     const connectionID = Onyx.connect({
-        key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}-backup`,
+        key: `${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`,
         callback: (backupTransaction) => {
             Onyx.disconnect(connectionID);
 
diff --git a/src/pages/EditRequestDistancePage.js b/src/pages/EditRequestDistancePage.js
index 0fca8aee4be9..e857f30db032 100644
--- a/src/pages/EditRequestDistancePage.js
+++ b/src/pages/EditRequestDistancePage.js
@@ -140,6 +140,6 @@ export default withOnyx({
         key: (props) => `${ONYXKEYS.COLLECTION.TRANSACTION}${props.transactionID}`,
     },
     transactionBackup: {
-        key: (props) => `${ONYXKEYS.COLLECTION.TRANSACTION}${props.transactionID}-backup`,
+        key: (props) => `${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${props.transactionID}`,
     },
 })(EditRequestDistancePage);

From 9aadfef916a8fbd1fa77da1e238c50d9f2f8b777 Mon Sep 17 00:00:00 2001
From: Antony Kithinzi <kithinzi97@gmail.com>
Date: Tue, 14 Nov 2023 01:47:02 +0300
Subject: [PATCH 03/14] ADD: Migration promise

---
 .../TransactionBackupsToCollection.js         | 77 +++++++++++++++++++
 1 file changed, 77 insertions(+)
 create mode 100644 src/libs/migrations/TransactionBackupsToCollection.js

diff --git a/src/libs/migrations/TransactionBackupsToCollection.js b/src/libs/migrations/TransactionBackupsToCollection.js
new file mode 100644
index 000000000000..4a43449f4798
--- /dev/null
+++ b/src/libs/migrations/TransactionBackupsToCollection.js
@@ -0,0 +1,77 @@
+import Onyx from 'react-native-onyx';
+import _ from 'underscore';
+import Log from '@libs/Log';
+import ONYXKEYS from '@src/ONYXKEYS';
+
+// This migration moves all the transaction backups stored in the main transactions collection (ONYXKEYS.COLLECTION.TRANSACTION)
+// to a reserved collection which only stores draft transactions (ONYXKEYS.COLLECTION.TRANSACTION_DRAFT).
+// The main purpose of this migration is that there is a possibility of transactions backups not getting filtered
+// by most functions which need use all transactions. Eg: getAllReportTransactions (src/libs/TransactionUtils.ts)
+// One problem which arose from having duplicate transactions in the collection is that for every distance request
+// which have their waypoints updated offline, we expect the ReportPreview component to display the default image of a pending map.
+// However, due to the presence of a transaction backup, an extra unexpected image of the previous map will be displayed.
+// The problem was further discussed in this PR -> https://github.com/Expensify/App/pull/30232#issuecomment-1781101722
+export default function () {
+    return new Promise((resolve) => {
+        const outerConnectionID = Onyx.connect({
+            key: ONYXKEYS.COLLECTION.TRANSACTION_DRAFT,
+            waitForCollectionCallback: true,
+            callback: (draftTransactions) => {
+                Onyx.disconnect(outerConnectionID);
+
+                // Check if transaction backups were already moved
+                if (draftTransactions) {
+                    Log.info(`[Migrate Onyx] Skipped TransactionBackupsToCollection migration because migration already happen`);
+                    return resolve();
+                }
+
+                const innerConnectionID = Onyx.connect({
+                    key: ONYXKEYS.COLLECTION.TRANSACTION,
+                    waitForCollectionCallback: true,
+                    callback: (transactions) => {
+                        Onyx.disconnect(innerConnectionID);
+
+                        // Check if there are any transactions.
+                        if (!transactions) {
+                            Log.info(`[Migrate Onyx] Skipped TransactionBackupsToCollection migration because there are no transactions in the main transactions collection`);
+                            return resolve();
+                        }
+
+                        const onyxData = _.reduce(
+                            _.keys(transactions),
+                            (result, transactionKey) => {
+                                if (!transactionKey.endsWith('-backup')) {
+                                    return result;
+                                }
+                                return {
+                                    ...result,
+
+                                    // We create all the transaction backups to the draft transactions collection
+                                    [`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactions[transactionKey].transactionID}`]: transactions[transactionKey],
+
+                                    // We delete the transaction backups stored the main transactions collection
+                                    [transactionKey]: null,
+                                };
+                            },
+                            {},
+                        );
+
+                        // Check if there are any available transaction backups to move
+                        if (!onyxData) {
+                            Log.info(`[Migrate Onyx] Skipped TransactionBackupsToCollection migration because there are no transaction backups in the main transactions collection`);
+                            return resolve();
+                        }
+
+                        // Moving the transaction backups from the main transactions collection to the draft transactions collection
+                        Onyx.multiSet(onyxData).then(() => {
+                            Log.info(
+                                `[Migrate Onyx] TransactionBackupsToCollection migration: successfully moved all transaction backups from the main transactions collection to the draft transactions collection`,
+                            );
+                            resolve();
+                        });
+                    },
+                });
+            },
+        });
+    });
+}

From 5c66d43807908271a00bd3da90281982a433d360 Mon Sep 17 00:00:00 2001
From: Antony Kithinzi <kithinzi97@gmail.com>
Date: Tue, 14 Nov 2023 01:49:31 +0300
Subject: [PATCH 04/14] ADD: TransactionsBackupsToCollection migration promise
 into the migrations execution queue

---
 src/libs/migrateOnyx.js | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/libs/migrateOnyx.js b/src/libs/migrateOnyx.js
index b65670819418..5daba3686208 100644
--- a/src/libs/migrateOnyx.js
+++ b/src/libs/migrateOnyx.js
@@ -3,6 +3,7 @@ import Log from './Log';
 import KeyReportActionsDraftByReportActionID from './migrations/KeyReportActionsDraftByReportActionID';
 import PersonalDetailsByAccountID from './migrations/PersonalDetailsByAccountID';
 import RenameReceiptFilename from './migrations/RenameReceiptFilename';
+import TransactionBackupsToCollection from './migrations/TransactionBackupsToCollection';
 
 export default function () {
     const startTime = Date.now();
@@ -10,7 +11,7 @@ export default function () {
 
     return new Promise((resolve) => {
         // Add all migrations to an array so they are executed in order
-        const migrationPromises = [PersonalDetailsByAccountID, RenameReceiptFilename, KeyReportActionsDraftByReportActionID];
+        const migrationPromises = [PersonalDetailsByAccountID, RenameReceiptFilename, KeyReportActionsDraftByReportActionID, TransactionBackupsToCollection];
 
         // Reduce all promises down to a single promise. All promises run in a linear fashion, waiting for the
         // previous promise to finish before moving onto the next one.

From a8027b715def8c1f7a30a333511609e1726fc71e Mon Sep 17 00:00:00 2001
From: Antony Kithinzi <kithinzi97@gmail.com>
Date: Wed, 15 Nov 2023 00:17:17 +0300
Subject: [PATCH 05/14] REFACTOR: Changing connection variable names and
 removing draft transactions collection check

---
 .../TransactionBackupsToCollection.js         | 68 +++++++++----------
 1 file changed, 31 insertions(+), 37 deletions(-)

diff --git a/src/libs/migrations/TransactionBackupsToCollection.js b/src/libs/migrations/TransactionBackupsToCollection.js
index 4a43449f4798..11a77039107a 100644
--- a/src/libs/migrations/TransactionBackupsToCollection.js
+++ b/src/libs/migrations/TransactionBackupsToCollection.js
@@ -13,54 +13,48 @@ import ONYXKEYS from '@src/ONYXKEYS';
 // The problem was further discussed in this PR -> https://github.com/Expensify/App/pull/30232#issuecomment-1781101722
 export default function () {
     return new Promise((resolve) => {
-        const outerConnectionID = Onyx.connect({
+        const transactionConnectionID = Onyx.connect({
             key: ONYXKEYS.COLLECTION.TRANSACTION_DRAFT,
             waitForCollectionCallback: true,
-            callback: (draftTransactions) => {
-                Onyx.disconnect(outerConnectionID);
+            callback: (transactions) => {
+                Onyx.disconnect(transactionConnectionID);
 
-                // Check if transaction backups were already moved
-                if (draftTransactions) {
-                    Log.info(`[Migrate Onyx] Skipped TransactionBackupsToCollection migration because migration already happen`);
+                // Check if there are any transactions.
+                if (!transactions) {
+                    Log.info(`[Migrate Onyx] Skipped TransactionBackupsToCollection migration because there are no transactions in the main transactions collection`);
                     return resolve();
                 }
 
-                const innerConnectionID = Onyx.connect({
-                    key: ONYXKEYS.COLLECTION.TRANSACTION,
-                    waitForCollectionCallback: true,
-                    callback: (transactions) => {
-                        Onyx.disconnect(innerConnectionID);
-
-                        // Check if there are any transactions.
-                        if (!transactions) {
-                            Log.info(`[Migrate Onyx] Skipped TransactionBackupsToCollection migration because there are no transactions in the main transactions collection`);
-                            return resolve();
+                const onyxData = _.reduce(
+                    _.keys(transactions),
+                    (result, transactionKey) => {
+                        if (!transactionKey.endsWith('-backup')) {
+                            return result;
                         }
+                        return {
+                            ...result,
 
-                        const onyxData = _.reduce(
-                            _.keys(transactions),
-                            (result, transactionKey) => {
-                                if (!transactionKey.endsWith('-backup')) {
-                                    return result;
-                                }
-                                return {
-                                    ...result,
+                            // We create all the transaction backups to the draft transactions collection
+                            [`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactions[transactionKey].transactionID}`]: transactions[transactionKey],
 
-                                    // We create all the transaction backups to the draft transactions collection
-                                    [`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactions[transactionKey].transactionID}`]: transactions[transactionKey],
+                            // We delete the transaction backups stored the main transactions collection
+                            [transactionKey]: null,
+                        };
+                    },
+                    {},
+                );
 
-                                    // We delete the transaction backups stored the main transactions collection
-                                    [transactionKey]: null,
-                                };
-                            },
-                            {},
-                        );
+                // Check if there are any available transaction backups to move
+                if (!onyxData) {
+                    Log.info(`[Migrate Onyx] Skipped TransactionBackupsToCollection migration because there are no transaction backups in the main transactions collection`);
+                    return resolve();
+                }
 
-                        // Check if there are any available transaction backups to move
-                        if (!onyxData) {
-                            Log.info(`[Migrate Onyx] Skipped TransactionBackupsToCollection migration because there are no transaction backups in the main transactions collection`);
-                            return resolve();
-                        }
+                const transactionDraftConnectionID = Onyx.connect({
+                    key: ONYXKEYS.COLLECTION.TRANSACTION,
+                    waitForCollectionCallback: true,
+                    callback: () => {
+                        Onyx.disconnect(transactionDraftConnectionID);
 
                         // Moving the transaction backups from the main transactions collection to the draft transactions collection
                         Onyx.multiSet(onyxData).then(() => {

From 300d39c2144684a6cb5afa6a46f1523de5dabcde Mon Sep 17 00:00:00 2001
From: Antony Kithinzi <kithinzi97@gmail.com>
Date: Wed, 15 Nov 2023 00:24:33 +0300
Subject: [PATCH 06/14] FIX: onyx collection key switch

---
 src/libs/migrations/TransactionBackupsToCollection.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libs/migrations/TransactionBackupsToCollection.js b/src/libs/migrations/TransactionBackupsToCollection.js
index 11a77039107a..074ace0a4796 100644
--- a/src/libs/migrations/TransactionBackupsToCollection.js
+++ b/src/libs/migrations/TransactionBackupsToCollection.js
@@ -14,7 +14,7 @@ import ONYXKEYS from '@src/ONYXKEYS';
 export default function () {
     return new Promise((resolve) => {
         const transactionConnectionID = Onyx.connect({
-            key: ONYXKEYS.COLLECTION.TRANSACTION_DRAFT,
+            key: ONYXKEYS.COLLECTION.TRANSACTION,
             waitForCollectionCallback: true,
             callback: (transactions) => {
                 Onyx.disconnect(transactionConnectionID);
@@ -51,7 +51,7 @@ export default function () {
                 }
 
                 const transactionDraftConnectionID = Onyx.connect({
-                    key: ONYXKEYS.COLLECTION.TRANSACTION,
+                    key: ONYXKEYS.COLLECTION.TRANSACTION_DRAFT,
                     waitForCollectionCallback: true,
                     callback: () => {
                         Onyx.disconnect(transactionDraftConnectionID);

From 045a0434e534fe7a0cd22f103fa5a54732f6afe5 Mon Sep 17 00:00:00 2001
From: Antony Kithinzi <kithinzi97@gmail.com>
Date: Wed, 15 Nov 2023 00:33:02 +0300
Subject: [PATCH 07/14] REFACTOR: removing unnecessary draft transaction
 connection

---
 .../TransactionBackupsToCollection.js         | 20 ++++++-------------
 1 file changed, 6 insertions(+), 14 deletions(-)

diff --git a/src/libs/migrations/TransactionBackupsToCollection.js b/src/libs/migrations/TransactionBackupsToCollection.js
index 074ace0a4796..e32df1876ba2 100644
--- a/src/libs/migrations/TransactionBackupsToCollection.js
+++ b/src/libs/migrations/TransactionBackupsToCollection.js
@@ -50,20 +50,12 @@ export default function () {
                     return resolve();
                 }
 
-                const transactionDraftConnectionID = Onyx.connect({
-                    key: ONYXKEYS.COLLECTION.TRANSACTION_DRAFT,
-                    waitForCollectionCallback: true,
-                    callback: () => {
-                        Onyx.disconnect(transactionDraftConnectionID);
-
-                        // Moving the transaction backups from the main transactions collection to the draft transactions collection
-                        Onyx.multiSet(onyxData).then(() => {
-                            Log.info(
-                                `[Migrate Onyx] TransactionBackupsToCollection migration: successfully moved all transaction backups from the main transactions collection to the draft transactions collection`,
-                            );
-                            resolve();
-                        });
-                    },
+                // Moving the transaction backups from the main transactions collection to the draft transactions collection
+                Onyx.multiSet(onyxData).then(() => {
+                    Log.info(
+                        `[Migrate Onyx] TransactionBackupsToCollection migration: successfully moved all transaction backups from the main transactions collection to the draft transactions collection`,
+                    );
+                    resolve();
                 });
             },
         });

From ae87c9a822484264b9e3e1b17d41f5116b6b297e Mon Sep 17 00:00:00 2001
From: Antony Kithinzi <kithinzi97@gmail.com>
Date: Sat, 18 Nov 2023 03:06:30 +0300
Subject: [PATCH 08/14] ADD: Wrote the javacript migration file,
 TransactionBackupsToCollection.js, to typescript

---
 .../TransactionBackupsToCollection.js         | 63 ------------------
 .../TransactionBackupsToCollection.ts         | 64 +++++++++++++++++++
 2 files changed, 64 insertions(+), 63 deletions(-)
 delete mode 100644 src/libs/migrations/TransactionBackupsToCollection.js
 create mode 100644 src/libs/migrations/TransactionBackupsToCollection.ts

diff --git a/src/libs/migrations/TransactionBackupsToCollection.js b/src/libs/migrations/TransactionBackupsToCollection.js
deleted file mode 100644
index e32df1876ba2..000000000000
--- a/src/libs/migrations/TransactionBackupsToCollection.js
+++ /dev/null
@@ -1,63 +0,0 @@
-import Onyx from 'react-native-onyx';
-import _ from 'underscore';
-import Log from '@libs/Log';
-import ONYXKEYS from '@src/ONYXKEYS';
-
-// This migration moves all the transaction backups stored in the main transactions collection (ONYXKEYS.COLLECTION.TRANSACTION)
-// to a reserved collection which only stores draft transactions (ONYXKEYS.COLLECTION.TRANSACTION_DRAFT).
-// The main purpose of this migration is that there is a possibility of transactions backups not getting filtered
-// by most functions which need use all transactions. Eg: getAllReportTransactions (src/libs/TransactionUtils.ts)
-// One problem which arose from having duplicate transactions in the collection is that for every distance request
-// which have their waypoints updated offline, we expect the ReportPreview component to display the default image of a pending map.
-// However, due to the presence of a transaction backup, an extra unexpected image of the previous map will be displayed.
-// The problem was further discussed in this PR -> https://github.com/Expensify/App/pull/30232#issuecomment-1781101722
-export default function () {
-    return new Promise((resolve) => {
-        const transactionConnectionID = Onyx.connect({
-            key: ONYXKEYS.COLLECTION.TRANSACTION,
-            waitForCollectionCallback: true,
-            callback: (transactions) => {
-                Onyx.disconnect(transactionConnectionID);
-
-                // Check if there are any transactions.
-                if (!transactions) {
-                    Log.info(`[Migrate Onyx] Skipped TransactionBackupsToCollection migration because there are no transactions in the main transactions collection`);
-                    return resolve();
-                }
-
-                const onyxData = _.reduce(
-                    _.keys(transactions),
-                    (result, transactionKey) => {
-                        if (!transactionKey.endsWith('-backup')) {
-                            return result;
-                        }
-                        return {
-                            ...result,
-
-                            // We create all the transaction backups to the draft transactions collection
-                            [`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactions[transactionKey].transactionID}`]: transactions[transactionKey],
-
-                            // We delete the transaction backups stored the main transactions collection
-                            [transactionKey]: null,
-                        };
-                    },
-                    {},
-                );
-
-                // Check if there are any available transaction backups to move
-                if (!onyxData) {
-                    Log.info(`[Migrate Onyx] Skipped TransactionBackupsToCollection migration because there are no transaction backups in the main transactions collection`);
-                    return resolve();
-                }
-
-                // Moving the transaction backups from the main transactions collection to the draft transactions collection
-                Onyx.multiSet(onyxData).then(() => {
-                    Log.info(
-                        `[Migrate Onyx] TransactionBackupsToCollection migration: successfully moved all transaction backups from the main transactions collection to the draft transactions collection`,
-                    );
-                    resolve();
-                });
-            },
-        });
-    });
-}
diff --git a/src/libs/migrations/TransactionBackupsToCollection.ts b/src/libs/migrations/TransactionBackupsToCollection.ts
new file mode 100644
index 000000000000..6d042c536e7c
--- /dev/null
+++ b/src/libs/migrations/TransactionBackupsToCollection.ts
@@ -0,0 +1,64 @@
+import isEmpty from 'lodash/isEmpty';
+import Onyx, {OnyxCollection} from 'react-native-onyx';
+import Log from '@libs/Log';
+import ONYXKEYS from '@src/ONYXKEYS';
+import {Transaction} from '@src/types/onyx';
+
+/**
+ * This migration moves all the transaction backups stored in the transaction collection, ONYXKEYS.COLLECTION.TRANSACTION,
+ * to a reserved collection which only stores draft transactions, ONYXKEYS.COLLECTION.TRANSACTION_DRAFT.
+ * The purpose of the migration is that there is a possibility of transaction backups are not filtered from
+ * by most functions when all transactions are fetched. Eg: getAllReportTransactions (src/libs/TransactionUtils.ts)
+ * One problem which arose from storing transaction backups with the other transactions is that for every distance request
+ * which have their waypoints updated offline, we expect the ReportPreview component to display the default image of a pending map.
+ * However, due to the presence of the transaction backup, the previous map image will be displayed alongside the current pending map.
+ * The problem was further discussed in this PR -> https://github.com/Expensify/App/pull/30232#issuecomment-178110172
+ */
+export default function (): Promise<void> {
+    return new Promise<void>((resolve) => {
+        const connectionID = Onyx.connect({
+            key: ONYXKEYS.COLLECTION.TRANSACTION,
+            waitForCollectionCallback: true,
+            callback: (transactions: OnyxCollection<Transaction>) => {
+                Onyx.disconnect(connectionID);
+
+                // Check if transaction collection is empty
+                if (isEmpty(transactions) || !transactions) {
+                    Log.info('[Migrate Onyx] Skipped TransactionBackupsToCollection migration because there are no transactions');
+                    return resolve;
+                }
+                const onyxData: OnyxCollection<Transaction> = {};
+
+                // Find all the transaction backups available
+                Object.keys(transactions).forEach((transactionOnyxKey: string) => {
+                    const transaction: Transaction | null = transactions[transactionOnyxKey];
+
+                    // Check if transaction is a backup
+                    if (!transactionOnyxKey.endsWith('-backup') || !transaction) {
+                        return;
+                    }
+
+                    // Create the transaction backup in the draft transaction collection
+                    onyxData[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transaction.transactionID}`] = transaction;
+
+                    // Delete the transaction backup stored the transaction collection
+                    onyxData[transactionOnyxKey] = null;
+                });
+
+                // Check if any transaction backups were found
+                if (isEmpty(onyxData)) {
+                    Log.info('[Migrate Onyx] Skipped TransactionBackupsToCollection migration because there are no transaction backups');
+                    return;
+                }
+
+                // eslint-disable-next-line no-console
+                console.info(onyxData);
+
+                Onyx.multiSet(onyxData as Partial<{string: [Transaction | null]}>).then(() => {
+                    Log.info('[Migrate Onyx] TransactionBackupsToCollection migration: Moved the transaction backups to the draft transaction collection');
+                    resolve();
+                });
+            },
+        });
+    });
+}

From b989b9d20c74ec58108f8d06f3c70172c91ebbde Mon Sep 17 00:00:00 2001
From: Antony Kithinzi <kithinzi97@gmail.com>
Date: Sun, 19 Nov 2023 00:52:57 +0300
Subject: [PATCH 09/14] Fix: Return resolve promise and removing console log
 while improve comments

---
 .../TransactionBackupsToCollection.ts         | 37 +++++++++----------
 1 file changed, 17 insertions(+), 20 deletions(-)

diff --git a/src/libs/migrations/TransactionBackupsToCollection.ts b/src/libs/migrations/TransactionBackupsToCollection.ts
index 6d042c536e7c..b5519692cc91 100644
--- a/src/libs/migrations/TransactionBackupsToCollection.ts
+++ b/src/libs/migrations/TransactionBackupsToCollection.ts
@@ -6,13 +6,13 @@ import {Transaction} from '@src/types/onyx';
 
 /**
  * This migration moves all the transaction backups stored in the transaction collection, ONYXKEYS.COLLECTION.TRANSACTION,
- * to a reserved collection which only stores draft transactions, ONYXKEYS.COLLECTION.TRANSACTION_DRAFT.
- * The purpose of the migration is that there is a possibility of transaction backups are not filtered from
+ * to a reserved collection that only stores draft transactions, ONYXKEYS.COLLECTION.TRANSACTION_DRAFT.
+ * The purpose of the migration is that there is a possibility that transaction backups are not filtered from
  * by most functions when all transactions are fetched. Eg: getAllReportTransactions (src/libs/TransactionUtils.ts)
- * One problem which arose from storing transaction backups with the other transactions is that for every distance request
+ * One problem that arose from storing transaction backups with the other transactions is that for every distance request
  * which have their waypoints updated offline, we expect the ReportPreview component to display the default image of a pending map.
  * However, due to the presence of the transaction backup, the previous map image will be displayed alongside the current pending map.
- * The problem was further discussed in this PR -> https://github.com/Expensify/App/pull/30232#issuecomment-178110172
+ * The problem was further discussed in this PR. https://github.com/Expensify/App/pull/30232#issuecomment-178110172
  */
 export default function (): Promise<void> {
     return new Promise<void>((resolve) => {
@@ -22,38 +22,35 @@ export default function (): Promise<void> {
             callback: (transactions: OnyxCollection<Transaction>) => {
                 Onyx.disconnect(connectionID);
 
-                // Check if transaction collection is empty
+                // Determine whether or not any transactions were found
                 if (isEmpty(transactions) || !transactions) {
                     Log.info('[Migrate Onyx] Skipped TransactionBackupsToCollection migration because there are no transactions');
-                    return resolve;
+                    return resolve();
                 }
                 const onyxData: OnyxCollection<Transaction> = {};
 
                 // Find all the transaction backups available
                 Object.keys(transactions).forEach((transactionOnyxKey: string) => {
                     const transaction: Transaction | null = transactions[transactionOnyxKey];
-
-                    // Check if transaction is a backup
+                    
+                    // Determine whether or not the transaction is a backup
                     if (!transactionOnyxKey.endsWith('-backup') || !transaction) {
-                        return;
-                    }
-
-                    // Create the transaction backup in the draft transaction collection
-                    onyxData[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transaction.transactionID}`] = transaction;
 
-                    // Delete the transaction backup stored the transaction collection
-                    onyxData[transactionOnyxKey] = null;
+                        // Create the transaction backup in the draft transaction collection
+                        onyxData[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transaction.transactionID}`] = transaction;
+    
+                        // Delete the transaction backup stored in the transaction collection
+                        onyxData[transactionOnyxKey] = null;
+                    }
                 });
 
-                // Check if any transaction backups were found
+                // Determine whether or not any transaction backups were found
                 if (isEmpty(onyxData)) {
                     Log.info('[Migrate Onyx] Skipped TransactionBackupsToCollection migration because there are no transaction backups');
-                    return;
+                    return resolve();
                 }
 
-                // eslint-disable-next-line no-console
-                console.info(onyxData);
-
+                // Move the transaction backups to the draft transaction collection
                 Onyx.multiSet(onyxData as Partial<{string: [Transaction | null]}>).then(() => {
                     Log.info('[Migrate Onyx] TransactionBackupsToCollection migration: Moved the transaction backups to the draft transaction collection');
                     resolve();

From dde30a1d3bded05925e1aebc69a81b66738b5a2f Mon Sep 17 00:00:00 2001
From: Antony Kithinzi <kithinzi97@gmail.com>
Date: Sun, 19 Nov 2023 01:29:08 +0300
Subject: [PATCH 10/14] FMT: Typescript checks

---
 src/libs/migrations/TransactionBackupsToCollection.ts | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/libs/migrations/TransactionBackupsToCollection.ts b/src/libs/migrations/TransactionBackupsToCollection.ts
index b5519692cc91..4b3fa24fd38c 100644
--- a/src/libs/migrations/TransactionBackupsToCollection.ts
+++ b/src/libs/migrations/TransactionBackupsToCollection.ts
@@ -32,13 +32,12 @@ export default function (): Promise<void> {
                 // Find all the transaction backups available
                 Object.keys(transactions).forEach((transactionOnyxKey: string) => {
                     const transaction: Transaction | null = transactions[transactionOnyxKey];
-                    
+
                     // Determine whether or not the transaction is a backup
                     if (!transactionOnyxKey.endsWith('-backup') || !transaction) {
-
                         // Create the transaction backup in the draft transaction collection
                         onyxData[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transaction.transactionID}`] = transaction;
-    
+
                         // Delete the transaction backup stored in the transaction collection
                         onyxData[transactionOnyxKey] = null;
                     }

From aa307498694afb52cbd30b3b7b2833c707166cfc Mon Sep 17 00:00:00 2001
From: Antony Kithinzi <kithinzi97@gmail.com>
Date: Sun, 19 Nov 2023 02:01:19 +0300
Subject: [PATCH 11/14] REFACTOR: Transaction null handler

---
 src/libs/migrations/TransactionBackupsToCollection.ts | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/libs/migrations/TransactionBackupsToCollection.ts b/src/libs/migrations/TransactionBackupsToCollection.ts
index 4b3fa24fd38c..59ec11a985d6 100644
--- a/src/libs/migrations/TransactionBackupsToCollection.ts
+++ b/src/libs/migrations/TransactionBackupsToCollection.ts
@@ -27,14 +27,16 @@ export default function (): Promise<void> {
                     Log.info('[Migrate Onyx] Skipped TransactionBackupsToCollection migration because there are no transactions');
                     return resolve();
                 }
+                
                 const onyxData: OnyxCollection<Transaction> = {};
 
                 // Find all the transaction backups available
                 Object.keys(transactions).forEach((transactionOnyxKey: string) => {
                     const transaction: Transaction | null = transactions[transactionOnyxKey];
 
-                    // Determine whether or not the transaction is a backup
-                    if (!transactionOnyxKey.endsWith('-backup') || !transaction) {
+                    // Determine whether the  transaction is a backup
+                    if (transactionOnyxKey.endsWith('-backup') && transaction) {
+
                         // Create the transaction backup in the draft transaction collection
                         onyxData[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transaction.transactionID}`] = transaction;
 
@@ -43,7 +45,7 @@ export default function (): Promise<void> {
                     }
                 });
 
-                // Determine whether or not any transaction backups were found
+                // Determine whether any transaction backups were found
                 if (isEmpty(onyxData)) {
                     Log.info('[Migrate Onyx] Skipped TransactionBackupsToCollection migration because there are no transaction backups');
                     return resolve();

From ad495ca6abc73ad879bdeccec1ee5d47881c5cdd Mon Sep 17 00:00:00 2001
From: Antony Kithinzi <kithinzi97@gmail.com>
Date: Sun, 19 Nov 2023 02:11:39 +0300
Subject: [PATCH 12/14] FMT: lint

---
 src/libs/migrations/TransactionBackupsToCollection.ts | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/libs/migrations/TransactionBackupsToCollection.ts b/src/libs/migrations/TransactionBackupsToCollection.ts
index 59ec11a985d6..64925ae1a286 100644
--- a/src/libs/migrations/TransactionBackupsToCollection.ts
+++ b/src/libs/migrations/TransactionBackupsToCollection.ts
@@ -27,7 +27,7 @@ export default function (): Promise<void> {
                     Log.info('[Migrate Onyx] Skipped TransactionBackupsToCollection migration because there are no transactions');
                     return resolve();
                 }
-                
+
                 const onyxData: OnyxCollection<Transaction> = {};
 
                 // Find all the transaction backups available
@@ -36,7 +36,6 @@ export default function (): Promise<void> {
 
                     // Determine whether the  transaction is a backup
                     if (transactionOnyxKey.endsWith('-backup') && transaction) {
-
                         // Create the transaction backup in the draft transaction collection
                         onyxData[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transaction.transactionID}`] = transaction;
 

From 80310c6639fd291eae5896b42c37ae50161d2744 Mon Sep 17 00:00:00 2001
From: Antony Kithinzi <kithinzi97@gmail.com>
Date: Sun, 19 Nov 2023 05:00:51 +0300
Subject: [PATCH 13/14] FMT: Grammar corrections

---
 src/libs/migrations/TransactionBackupsToCollection.ts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libs/migrations/TransactionBackupsToCollection.ts b/src/libs/migrations/TransactionBackupsToCollection.ts
index 64925ae1a286..b0566c95894f 100644
--- a/src/libs/migrations/TransactionBackupsToCollection.ts
+++ b/src/libs/migrations/TransactionBackupsToCollection.ts
@@ -7,8 +7,8 @@ import {Transaction} from '@src/types/onyx';
 /**
  * This migration moves all the transaction backups stored in the transaction collection, ONYXKEYS.COLLECTION.TRANSACTION,
  * to a reserved collection that only stores draft transactions, ONYXKEYS.COLLECTION.TRANSACTION_DRAFT.
- * The purpose of the migration is that there is a possibility that transaction backups are not filtered from
- * by most functions when all transactions are fetched. Eg: getAllReportTransactions (src/libs/TransactionUtils.ts)
+ * The purpose of the migration is that there is a possibility that transaction backups are not filtered
+ * by most functions when all transactions are fetched, e.g, getAllReportTransactions (src/libs/TransactionUtils.ts)
  * One problem that arose from storing transaction backups with the other transactions is that for every distance request
  * which have their waypoints updated offline, we expect the ReportPreview component to display the default image of a pending map.
  * However, due to the presence of the transaction backup, the previous map image will be displayed alongside the current pending map.

From 6fe35c4197975ef2793104f303c756c8884f0b28 Mon Sep 17 00:00:00 2001
From: Antony Kithinzi <kithinzi97@gmail.com>
Date: Mon, 20 Nov 2023 23:11:11 +0300
Subject: [PATCH 14/14] REFACTOR: Replacing  third party function, isEmpty, for
 TS native functions to imporve performance. Also, edited file description and
 comments to improve clarity, conciseness and grammar

---
 .../TransactionBackupsToCollection.ts         | 25 ++++++++-----------
 1 file changed, 11 insertions(+), 14 deletions(-)

diff --git a/src/libs/migrations/TransactionBackupsToCollection.ts b/src/libs/migrations/TransactionBackupsToCollection.ts
index b0566c95894f..ddaa691b8d47 100644
--- a/src/libs/migrations/TransactionBackupsToCollection.ts
+++ b/src/libs/migrations/TransactionBackupsToCollection.ts
@@ -1,17 +1,14 @@
-import isEmpty from 'lodash/isEmpty';
 import Onyx, {OnyxCollection} from 'react-native-onyx';
 import Log from '@libs/Log';
 import ONYXKEYS from '@src/ONYXKEYS';
 import {Transaction} from '@src/types/onyx';
 
 /**
- * This migration moves all the transaction backups stored in the transaction collection, ONYXKEYS.COLLECTION.TRANSACTION,
- * to a reserved collection that only stores draft transactions, ONYXKEYS.COLLECTION.TRANSACTION_DRAFT.
- * The purpose of the migration is that there is a possibility that transaction backups are not filtered
- * by most functions when all transactions are fetched, e.g, getAllReportTransactions (src/libs/TransactionUtils.ts)
- * One problem that arose from storing transaction backups with the other transactions is that for every distance request
- * which have their waypoints updated offline, we expect the ReportPreview component to display the default image of a pending map.
- * However, due to the presence of the transaction backup, the previous map image will be displayed alongside the current pending map.
+ * This migration moves all the transaction backups stored in the transaction collection, ONYXKEYS.COLLECTION.TRANSACTION, to a reserved collection that only
+ * stores draft transactions, ONYXKEYS.COLLECTION.TRANSACTION_DRAFT. The purpose of the migration is that there is a possibility that transaction backups are
+ * not filtered by most functions, e.g, getAllReportTransactions (src/libs/TransactionUtils.ts). One problem that arose from storing transaction backups with
+ * the other transactions is that for every distance request which have their waypoints updated offline, we expect the ReportPreview component to display the
+ * default image of a pending map. However, due to the presence of the transaction backup, the previous map image will be displayed alongside the pending map.
  * The problem was further discussed in this PR. https://github.com/Expensify/App/pull/30232#issuecomment-178110172
  */
 export default function (): Promise<void> {
@@ -22,8 +19,8 @@ export default function (): Promise<void> {
             callback: (transactions: OnyxCollection<Transaction>) => {
                 Onyx.disconnect(connectionID);
 
-                // Determine whether or not any transactions were found
-                if (isEmpty(transactions) || !transactions) {
+                // Determine whether any transactions were stored
+                if (!transactions || Object.keys(transactions).length === 0) {
                     Log.info('[Migrate Onyx] Skipped TransactionBackupsToCollection migration because there are no transactions');
                     return resolve();
                 }
@@ -34,7 +31,7 @@ export default function (): Promise<void> {
                 Object.keys(transactions).forEach((transactionOnyxKey: string) => {
                     const transaction: Transaction | null = transactions[transactionOnyxKey];
 
-                    // Determine whether the  transaction is a backup
+                    // Determine whether or not the transaction is a backup
                     if (transactionOnyxKey.endsWith('-backup') && transaction) {
                         // Create the transaction backup in the draft transaction collection
                         onyxData[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transaction.transactionID}`] = transaction;
@@ -44,15 +41,15 @@ export default function (): Promise<void> {
                     }
                 });
 
-                // Determine whether any transaction backups were found
-                if (isEmpty(onyxData)) {
+                // Determine whether any transaction backups are found
+                if (Object.keys(onyxData).length === 0) {
                     Log.info('[Migrate Onyx] Skipped TransactionBackupsToCollection migration because there are no transaction backups');
                     return resolve();
                 }
 
                 // Move the transaction backups to the draft transaction collection
                 Onyx.multiSet(onyxData as Partial<{string: [Transaction | null]}>).then(() => {
-                    Log.info('[Migrate Onyx] TransactionBackupsToCollection migration: Moved the transaction backups to the draft transaction collection');
+                    Log.info('[Migrate Onyx] TransactionBackupsToCollection migration: Successfully moved all the transaction backups to the draft transaction collection');
                     resolve();
                 });
             },
