Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions __mocks__/reportData/transactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const TRANSACTION_ID_R98765 = 'TRANSACTION_ID_R98765';
const receiptR14932 = {
state: CONST.IOU.RECEIPT_STATE.OPEN,
source: 'mockData/eReceiptBGs/eReceiptBG_pink.png',
filename: 'test.html',
};

const transactionR14932: Transaction = {
Expand All @@ -22,7 +23,6 @@ const transactionR14932: Transaction = {
status: CONST.TRANSACTION.STATUS.POSTED,
receipt: receiptR14932,
merchant: 'Acme',
filename: 'test.html',
created: '2025-02-14',
inserted: '2025-02-14 08:12:19',
billable: false,
Expand Down Expand Up @@ -66,7 +66,6 @@ const transactionR98765: Transaction = {
bank: '',
cardNumber: '',
category: '',
filename: '',
modifiedCreated: '',
modifiedCurrency: '',
modifiedMerchant: '',
Expand Down
3 changes: 1 addition & 2 deletions src/hooks/useRestartOnReceiptFailure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import type {OnyxEntry} from 'react-native-onyx';
import {checkIfScanFileCanBeRead, setMoneyRequestReceipt} from '@libs/actions/IOU';
import {removeDraftTransactions} from '@libs/actions/TransactionEdit';
import {isLocalFile as isLocalFileUtil} from '@libs/fileDownload/FileUtils';
import getReceiptFilenameFromTransaction from '@libs/getReceiptFilenameFromTransaction';
import {navigateToStartMoneyRequestStep} from '@libs/IOUUtils';
import {getRequestType} from '@libs/TransactionUtils';
import type {IOUAction, IOUType} from '@src/CONST';
Expand All @@ -21,7 +20,7 @@ const useRestartOnReceiptFailure = (transaction: OnyxEntry<Transaction>, reportI
if (!transaction || action !== CONST.IOU.ACTION.CREATE) {
return;
}
const itemReceiptFilename = getReceiptFilenameFromTransaction(transaction);
const itemReceiptFilename = transaction.receipt?.filename;
const itemReceiptPath = transaction.receipt?.source;
const itemReceiptType = transaction.receipt?.type;
const isLocalFile = isLocalFileUtil(itemReceiptPath);
Expand Down
2 changes: 0 additions & 2 deletions src/libs/DebugUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -944,7 +944,6 @@ function validateTransactionDraftProperty(key: keyof Transaction, value: string)
case 'category':
case 'merchant':
case 'taxCode':
case 'filename':
case 'modifiedCurrency':
case 'modifiedMerchant':
case 'transactionID':
Expand Down Expand Up @@ -1054,7 +1053,6 @@ function validateTransactionDraftProperty(key: keyof Transaction, value: string)
created: CONST.RED_BRICK_ROAD_PENDING_ACTION,
currency: CONST.RED_BRICK_ROAD_PENDING_ACTION,
errors: CONST.RED_BRICK_ROAD_PENDING_ACTION,
filename: CONST.RED_BRICK_ROAD_PENDING_ACTION,
iouRequestType: CONST.RED_BRICK_ROAD_PENDING_ACTION,
merchant: CONST.RED_BRICK_ROAD_PENDING_ACTION,
modifiedAmount: CONST.RED_BRICK_ROAD_PENDING_ACTION,
Expand Down
5 changes: 2 additions & 3 deletions src/libs/MergeTransactionUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import type {MergeTransaction, Transaction} from '@src/types/onyx';
import type {Attendee} from '@src/types/onyx/IOU';
import SafeString from '@src/utils/SafeString';
import {convertToDisplayString} from './CurrencyUtils';
import getReceiptFilenameFromTransaction from './getReceiptFilenameFromTransaction';
import Parser from './Parser';
import {getCommaSeparatedTagNameWithSanitizedColons} from './PolicyUtils';
import {getIOUActionForReportID} from './ReportActionsUtils';
Expand Down Expand Up @@ -66,15 +65,15 @@ function getMergeFieldErrorText(translate: LocaleContextProps['translate'], merg
*/
function fillMissingReceiptSource(transaction: Transaction) {
// If receipt.source already exists, no need to modify
if (!transaction.receipt || !!transaction.receipt?.source || !getReceiptFilenameFromTransaction(transaction)) {
if (!transaction.receipt || !!transaction.receipt.source || !transaction.receipt.filename) {
return transaction;
}

return {
...transaction,
receipt: {
...transaction.receipt,
source: `${RECEIPT_SOURCE_URL}${getReceiptFilenameFromTransaction(transaction)}`,
source: `${RECEIPT_SOURCE_URL}${transaction.receipt.filename}`,
},
};
}
Expand Down
3 changes: 1 addition & 2 deletions src/libs/ReceiptUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import ROUTES from '@src/ROUTES';
import type {ShareTempFile, Transaction} from '@src/types/onyx';
import type {ReceiptError, ReceiptSource} from '@src/types/onyx/Transaction';
import {isLocalFile as isLocalFileUtils, splitExtensionFromFileName} from './fileDownload/FileUtils';
import getReceiptFilenameFromTransaction from './getReceiptFilenameFromTransaction';
import {hasReceipt, hasReceiptSource, isFetchingWaypointsFromServer} from './TransactionUtils';

type ThumbnailAndImageURI = {
Expand Down Expand Up @@ -39,7 +38,7 @@ function getThumbnailAndImageURIs(transaction: OnyxEntry<Transaction>, receiptPa
// URI to image, i.e. blob:new.expensify.com/9ef3a018-4067-47c6-b29f-5f1bd35f213d or expensify.com/receipts/w_e616108497ef940b7210ec6beb5a462d01a878f4.jpg
const path = errors?.source ?? transaction?.receipt?.source ?? receiptPath ?? '';
// filename of uploaded image or last part of remote URI
const filename = errors?.filename ?? getReceiptFilenameFromTransaction(transaction) ?? receiptFileName ?? '';
const filename = errors?.filename ?? transaction?.receipt?.filename ?? receiptFileName ?? '';
const isReceiptImage = Str.isImage(filename);
const hasEReceipt = !hasReceiptSource(transaction) && transaction?.hasEReceipt;
const isReceiptPDF = Str.isPDF(filename);
Expand Down
59 changes: 11 additions & 48 deletions src/libs/actions/IOU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ import DateUtils from '@libs/DateUtils';
import DistanceRequestUtils from '@libs/DistanceRequestUtils';
import {getMicroSecondOnyxErrorObject, getMicroSecondOnyxErrorWithTranslationKey} from '@libs/ErrorUtils';
import {readFileAsync} from '@libs/fileDownload/FileUtils';
import getReceiptFilenameFromTransaction from '@libs/getReceiptFilenameFromTransaction';
import GoogleTagManager from '@libs/GoogleTagManager';
import {
calculateAmount as calculateIOUAmount,
Expand Down Expand Up @@ -2056,7 +2055,7 @@ function buildOnyxDataForMoneyRequest(moneyRequestParams: BuildOnyxDataForMoneyR
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`,
value: {
errors: getReceiptError(transaction.receipt, getReceiptFilenameFromTransaction(transaction), isScanRequest, errorKey, CONST.IOU.ACTION_PARAMS.MONEY_REQUEST, retryParams),
errors: getReceiptError(transaction.receipt, transaction.receipt?.filename, isScanRequest, errorKey, CONST.IOU.ACTION_PARAMS.MONEY_REQUEST, retryParams),
pendingFields: clearedPendingFields,
},
},
Expand All @@ -2067,29 +2066,15 @@ function buildOnyxDataForMoneyRequest(moneyRequestParams: BuildOnyxDataForMoneyR
...(shouldCreateNewMoneyRequestReport
? {
[iou.createdAction.reportActionID]: {
errors: getReceiptError(
transaction.receipt,
getReceiptFilenameFromTransaction(transaction),
isScanRequest,
errorKey,
CONST.IOU.ACTION_PARAMS.MONEY_REQUEST,
retryParams,
),
errors: getReceiptError(transaction.receipt, transaction.receipt?.filename, isScanRequest, errorKey, CONST.IOU.ACTION_PARAMS.MONEY_REQUEST, retryParams),
},
[iou.action.reportActionID]: {
errors: getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateFailureMessage'),
},
}
: {
[iou.action.reportActionID]: {
errors: getReceiptError(
transaction.receipt,
getReceiptFilenameFromTransaction(transaction),
isScanRequest,
errorKey,
CONST.IOU.ACTION_PARAMS.MONEY_REQUEST,
retryParams,
),
errors: getReceiptError(transaction.receipt, transaction.receipt?.filename, isScanRequest, errorKey, CONST.IOU.ACTION_PARAMS.MONEY_REQUEST, retryParams),
},
}),
},
Expand Down Expand Up @@ -2515,7 +2500,7 @@ function buildOnyxDataForInvoice(invoiceParams: BuildOnyxDataForInvoiceParams):
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iou.report?.reportID}`,
value: {
[iou.createdAction.reportActionID]: {
errors: getReceiptError(transactionParams.transaction.receipt, getReceiptFilenameFromTransaction(transactionParams.transaction), false, errorKey),
errors: getReceiptError(transactionParams.transaction.receipt, transactionParams.transaction.receipt?.filename, false, errorKey),
},
[iou.action.reportActionID]: {
errors: getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateInvoiceFailureMessage'),
Expand Down Expand Up @@ -2921,29 +2906,15 @@ function buildOnyxDataForTrackExpense({
...(shouldCreateNewMoneyRequestReport
? {
[iouCreatedAction.reportActionID]: {
errors: getReceiptError(
transaction.receipt,
getReceiptFilenameFromTransaction(transaction),
isScanRequest,
undefined,
CONST.IOU.ACTION_PARAMS.TRACK_EXPENSE,
retryParams,
),
errors: getReceiptError(transaction.receipt, transaction.receipt?.filename, isScanRequest, undefined, CONST.IOU.ACTION_PARAMS.TRACK_EXPENSE, retryParams),
},
[iouAction.reportActionID]: {
errors: getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericCreateFailureMessage'),
},
}
: {
[iouAction.reportActionID]: {
errors: getReceiptError(
transaction.receipt,
getReceiptFilenameFromTransaction(transaction),
isScanRequest,
undefined,
CONST.IOU.ACTION_PARAMS.TRACK_EXPENSE,
retryParams,
),
errors: getReceiptError(transaction.receipt, transaction.receipt?.filename, isScanRequest, undefined, CONST.IOU.ACTION_PARAMS.TRACK_EXPENSE, retryParams),
},
}),
},
Expand All @@ -2955,14 +2926,7 @@ function buildOnyxDataForTrackExpense({
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport?.reportID}`,
value: {
[iouAction.reportActionID]: {
errors: getReceiptError(
transaction.receipt,
getReceiptFilenameFromTransaction(transaction),
isScanRequest,
undefined,
CONST.IOU.ACTION_PARAMS.TRACK_EXPENSE,
retryParams,
),
errors: getReceiptError(transaction.receipt, transaction.receipt?.filename, isScanRequest, undefined, CONST.IOU.ACTION_PARAMS.TRACK_EXPENSE, retryParams),
},
},
});
Expand Down Expand Up @@ -2994,7 +2958,7 @@ function buildOnyxDataForTrackExpense({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`,
value: {
errors: getReceiptError(transaction.receipt, getReceiptFilenameFromTransaction(transaction), isScanRequest, undefined, CONST.IOU.ACTION_PARAMS.TRACK_EXPENSE, retryParams),
errors: getReceiptError(transaction.receipt, transaction.receipt?.filename, isScanRequest, undefined, CONST.IOU.ACTION_PARAMS.TRACK_EXPENSE, retryParams),
pendingFields: clearedPendingFields,
},
},
Expand Down Expand Up @@ -4234,7 +4198,6 @@ function getTrackExpenseInformation(params: GetTrackExpenseInformationParams): T

// STEP 3: Build optimistic receipt and transaction
const existingTransaction = allTransactionDrafts[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${existingTransactionID ?? CONST.IOU.OPTIMISTIC_TRANSACTION_ID}`];
const filename = getReceiptFilenameFromTransaction(existingTransaction);
const isDistanceRequest = existingTransaction && isDistanceRequestTransactionUtils(existingTransaction);
const isManualDistanceRequest = existingTransaction && isManualDistanceRequestTransactionUtils(existingTransaction);
let optimisticTransaction = buildOptimisticTransaction({
Expand All @@ -4257,7 +4220,7 @@ function getTrackExpenseInformation(params: GetTrackExpenseInformationParams): T
billable,
pendingFields: isDistanceRequest && !isManualDistanceRequest ? {waypoints: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD} : undefined,
reimbursable,
filename,
filename: existingTransaction?.receipt?.filename,
attendees,
},
});
Expand Down Expand Up @@ -7694,7 +7657,7 @@ function startSplitBill({
},
});

const filename = getReceiptFilenameFromTransaction(splitTransaction);
const filename = splitTransaction.receipt?.filename;

// Note: The created action must be optimistically generated before the IOU action so there's no chance that the created action appears after the IOU action in the chat
const splitChatCreatedReportAction = buildOptimisticCreatedReportAction(currentUserEmailForIOUSplit);
Expand Down Expand Up @@ -8170,7 +8133,7 @@ function completeSplitBill(
billable: updatedTransaction?.billable,
reimbursable: updatedTransaction?.reimbursable,
source: CONST.IOU.TYPE.SPLIT,
filename: getReceiptFilenameFromTransaction(updatedTransaction),
filename: updatedTransaction?.receipt?.filename,
},
});
oneOnOneIOUReport.transactionCount = (oneOnOneIOUReport.transactionCount ?? 0) + 1;
Expand Down
7 changes: 0 additions & 7 deletions src/libs/getReceiptFilenameFromTransaction.ts

This file was deleted.

8 changes: 5 additions & 3 deletions src/libs/migrations/RenameReceiptFilename.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {isEmptyObject} from '@src/types/utils/EmptyObject';

type TransactionKey = `${typeof ONYXKEYS.COLLECTION.TRANSACTION}${string}`;

type OldTransaction = Transaction & {filename?: string};

// This migration moves filename from the transaction root to transaction.receipt.filename to match the database structure.
export default function () {
return new Promise<void>((resolve) => {
Expand All @@ -15,15 +17,15 @@ export default function () {
const connection = Onyx.connectWithoutView({
key: ONYXKEYS.COLLECTION.TRANSACTION,
waitForCollectionCallback: true,
callback: (transactions: OnyxCollection<Transaction>) => {
callback: (transactions: OnyxCollection<OldTransaction>) => {
Onyx.disconnect(connection);

if (!transactions || isEmptyObject(transactions)) {
Log.info('[Migrate Onyx] Skipped migration RenameReceiptFilename because there are no transactions');
return resolve();
}

const transactionsWithReceipt: Array<OnyxEntry<Transaction>> = Object.values(transactions).filter((transaction) => transaction?.filename);
const transactionsWithReceipt: Array<OnyxEntry<OldTransaction>> = Object.values(transactions).filter((transaction) => transaction?.filename);
if (!transactionsWithReceipt?.length) {
Log.info('[Migrate Onyx] Skipped migration RenameReceiptFilename because there were no transactions with the filename property');
return resolve();
Expand All @@ -43,7 +45,7 @@ export default function () {
};
return acc;
},
{} as Record<TransactionKey, NullishDeep<Transaction>>,
{} as Record<TransactionKey, NullishDeep<OldTransaction>>,
);

// eslint-disable-next-line rulesdir/prefer-actions-set-data
Expand Down
3 changes: 1 addition & 2 deletions src/pages/iou/SplitBillDetailsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import {completeSplitBill, setDraftSplitTransaction} from '@libs/actions/IOU';
import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
import getReceiptFilenameFromTransaction from '@libs/getReceiptFilenameFromTransaction';
import Navigation from '@libs/Navigation/Navigation';
import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
import type {SplitDetailsNavigatorParamList} from '@libs/Navigation/types';
Expand Down Expand Up @@ -134,7 +133,7 @@ function SplitBillDetailsPage({route, report, reportAction}: SplitBillDetailsPag
isReadOnly={!isEditingSplitBill}
shouldShowSmartScanFields
receiptPath={transaction?.receipt?.source}
receiptFilename={getReceiptFilenameFromTransaction(transaction)}
receiptFilename={transaction?.receipt?.filename}
isDistanceRequest={isDistanceRequest}
isManualDistanceRequest={isManualDistanceRequest}
isEditingSplitBill={isEditingSplitBill}
Expand Down
5 changes: 2 additions & 3 deletions src/pages/iou/request/step/IOURequestStepConfirmation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ import {isLocalFile as isLocalFileFileUtils} from '@libs/fileDownload/FileUtils'
import validateReceiptFile from '@libs/fileDownload/validateReceiptFile';
import getCurrentPosition from '@libs/getCurrentPosition';
import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
import getReceiptFilenameFromTransaction from '@libs/getReceiptFilenameFromTransaction';
import {
isMovingTransactionFromTrackExpense as isMovingTransactionFromTrackExpenseIOUUtils,
navigateToStartMoneyRequestStep,
Expand Down Expand Up @@ -243,7 +242,7 @@ function IOURequestStepConfirmation({
const archivedReportsIdSet = useArchivedReportsIdSet();
const parentReportAction = useParentReportAction(viewTourTaskReport);

const receiptFilename = getReceiptFilenameFromTransaction(transaction);
const receiptFilename = transaction?.receipt?.filename;
const receiptPath = transaction?.receipt?.source;
const isEditingReceipt = hasReceipt(transaction);
const customUnitRateID = getRateID(transaction) ?? '';
Expand Down Expand Up @@ -461,7 +460,7 @@ function IOURequestStepConfirmation({

Promise.all(
transactions.map((item) => {
const itemReceiptFilename = getReceiptFilenameFromTransaction(item);
const itemReceiptFilename = item.receipt?.filename;
const itemReceiptPath = item.receipt?.source;
const itemReceiptType = item.receipt?.type;
const isLocalFile = isLocalFileFileUtils(itemReceiptPath);
Expand Down
Loading
Loading