diff --git a/src/libs/DebugUtils.ts b/src/libs/DebugUtils.ts index 36f7ebda3bc9..c72cb7de9987 100644 --- a/src/libs/DebugUtils.ts +++ b/src/libs/DebugUtils.ts @@ -956,6 +956,7 @@ function validateTransactionDraftProperty(key: keyof Transaction, value: string) case 'hasEReceipt': case 'shouldShowOriginalAmount': case 'managedCard': + case 'wasMerchantCleared': return validateBoolean(value); case 'amount': case 'taxAmount': @@ -1078,6 +1079,7 @@ function validateTransactionDraftProperty(key: keyof Transaction, value: string) inserted: CONST.RED_BRICK_ROAD_PENDING_ACTION, accountant: CONST.RED_BRICK_ROAD_PENDING_ACTION, splitExpenses: CONST.RED_BRICK_ROAD_PENDING_ACTION, + wasMerchantCleared: CONST.RED_BRICK_ROAD_PENDING_ACTION, }, 'string', ); diff --git a/src/libs/TransactionUtils/index.ts b/src/libs/TransactionUtils/index.ts index 090971f1be60..420dc077cc9c 100644 --- a/src/libs/TransactionUtils/index.ts +++ b/src/libs/TransactionUtils/index.ts @@ -420,6 +420,10 @@ function getUpdatedTransaction({ shouldStopSmartscan = true; } + if (Object.hasOwn(transactionChanges, 'wasMerchantCleared')) { + updatedTransaction.wasMerchantCleared = transactionChanges.wasMerchantCleared; + } + if (Object.hasOwn(transactionChanges, 'waypoints')) { updatedTransaction.modifiedWaypoints = transactionChanges.waypoints; updatedTransaction.isLoading = true; @@ -665,8 +669,12 @@ function isFetchingWaypointsFromServer(transaction: OnyxInputOrEntry, policyParam: OnyxEntry = undefined): string { - if (transaction && isDistanceRequest(transaction)) { - const report = getReportOrDraftReport(transaction.reportID); + if (!transaction) { + return ''; + } + + const report = getReportOrDraftReport(transaction.reportID); + if (isDistanceRequest(transaction)) { // This will be fixed as part of https://github.com/Expensify/Expensify/issues/507850 // eslint-disable-next-line deprecation/deprecation const policy = policyParam ?? getPolicy(report?.policyID); @@ -677,7 +685,12 @@ function getMerchant(transaction: OnyxInputOrEntry, policyParam: On toLocaleDigit(TranslationStore.getCurrentLocale(), digit), ); } - return transaction?.modifiedMerchant ? transaction.modifiedMerchant : (transaction?.merchant ?? ''); + + // Check if merchant was intentionally cleared by user (only for personal expenses) + if (transaction.wasMerchantCleared) { + return ''; + } + return transaction.modifiedMerchant ? transaction.modifiedMerchant : (transaction.merchant ?? ''); } function getMerchantOrDescription(transaction: OnyxEntry) { diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index d8e0ef6dde5b..770537028f42 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -4592,10 +4592,16 @@ function updateMoneyRequestMerchant( policy: OnyxEntry, policyTagList: OnyxEntry, policyCategories: OnyxEntry, + wasMerchantCleared?: boolean, ) { const transactionChanges: TransactionChanges = { merchant: value, }; + + if (wasMerchantCleared !== undefined) { + transactionChanges.wasMerchantCleared = wasMerchantCleared; + } + const transactionThreadReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`] ?? null; const parentReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReport?.parentReportID}`] ?? null; let data: UpdateMoneyRequestData; diff --git a/src/pages/iou/request/step/IOURequestStepMerchant.tsx b/src/pages/iou/request/step/IOURequestStepMerchant.tsx index af14bc01e941..a1702a5b2d08 100644 --- a/src/pages/iou/request/step/IOURequestStepMerchant.tsx +++ b/src/pages/iou/request/step/IOURequestStepMerchant.tsx @@ -100,10 +100,26 @@ function IOURequestStepMerchant({ navigateBack(); return; } - // When creating/editing an expense, newMerchant can be blank so we fall back on PARTIAL_TRANSACTION_MERCHANT - setMoneyRequestMerchant(transactionID, newMerchant || CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT, !isEditing); + + // Check if merchant was intentionally cleared by user + const existingMerchantValue = merchant === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT ? '' : merchant; + const wasMerchantCleared = newMerchant === '' && existingMerchantValue !== ''; + + // Determine the merchant value to save + let merchantValue: string; + if (wasMerchantCleared) { + if (isMerchantRequired) { + return; + } + merchantValue = ''; + } else { + // Fallback to PARTIAL_TRANSACTION_MERCHANT only if merchant is null or undefined + merchantValue = newMerchant ?? CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT; + } + + setMoneyRequestMerchant(transactionID, merchantValue, !isEditing); if (isEditing) { - updateMoneyRequestMerchant(transactionID, reportID, newMerchant || CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT, policy, policyTags, policyCategories); + updateMoneyRequestMerchant(transactionID, reportID, merchantValue, policy, policyTags, policyCategories, wasMerchantCleared && !isMerchantRequired); } navigateBack(); }; diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts index 6898997336c0..f0ac31d9c809 100644 --- a/src/types/onyx/Transaction.ts +++ b/src/types/onyx/Transaction.ts @@ -548,6 +548,9 @@ type Transaction = OnyxCommon.OnyxValueWithOfflineFeedback< /** The inserted time of the transaction */ inserted?: string; + + /** Whether the merchant field was intentionally cleared by the user */ + wasMerchantCleared?: boolean; }, keyof Comment | keyof TransactionCustomUnit | 'attendees' >;