diff --git a/src/libs/Violations/ViolationsUtils.ts b/src/libs/Violations/ViolationsUtils.ts index 85060e157196..d24e21957f26 100644 --- a/src/libs/Violations/ViolationsUtils.ts +++ b/src/libs/Violations/ViolationsUtils.ts @@ -257,14 +257,16 @@ const ViolationsUtils = { } } - const shouldShowSmartScanFailedError = isScanRequest && updatedTransaction.receipt?.state === CONST.IOU.RECEIPT_STATE.SCAN_FAILED; + // Only show SmartScan failed when scan failed AND the user hasn't filled required fields yet + const hasUserStartedFixingSmartscan = !TransactionUtils.isAmountMissing(updatedTransaction) || !TransactionUtils.isMerchantMissing(updatedTransaction); + const shouldShowSmartScanFailedError = + isScanRequest && + updatedTransaction.receipt?.state === CONST.IOU.RECEIPT_STATE.SCAN_FAILED && + TransactionUtils.hasMissingSmartscanFields(updatedTransaction, iouReport ?? undefined) && + !hasUserStartedFixingSmartscan; const hasSmartScanFailedError = transactionViolations.some((violation) => violation.name === CONST.VIOLATIONS.SMARTSCAN_FAILED); if (shouldShowSmartScanFailedError && !hasSmartScanFailedError) { - return { - onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${updatedTransaction.transactionID}`, - value: [{name: CONST.VIOLATIONS.SMARTSCAN_FAILED, type: CONST.VIOLATION_TYPES.WARNING, showInReview: true}], - }; + newTransactionViolations.push({name: CONST.VIOLATIONS.SMARTSCAN_FAILED, type: CONST.VIOLATION_TYPES.WARNING, showInReview: true}); } if (!shouldShowSmartScanFailedError && hasSmartScanFailedError) { newTransactionViolations = reject(newTransactionViolations, {name: CONST.VIOLATIONS.SMARTSCAN_FAILED}); diff --git a/tests/unit/ViolationUtilsTest.ts b/tests/unit/ViolationUtilsTest.ts index 3ae011a20d00..4fa2b34fafa8 100644 --- a/tests/unit/ViolationUtilsTest.ts +++ b/tests/unit/ViolationUtilsTest.ts @@ -365,7 +365,7 @@ describe('getViolationsOnyxData', () => { expect(result.value).toEqual(expect.arrayContaining([missingCategoryViolation, ...transactionViolations])); }); - it('should only return smartscanFailed violation for smart scan failed transactions', () => { + it('should keep other violations while adding smartscanFailed for smart scan failed transactions', () => { const partialTransaction = { ...transaction, amount: 0, @@ -375,7 +375,43 @@ describe('getViolationsOnyxData', () => { receipt: {state: CONST.IOU.RECEIPT_STATE.SCAN_FAILED}, }; const result = ViolationsUtils.getViolationsOnyxData(partialTransaction, transactionViolations, policy, policyTags, policyCategories, false, false); - expect(result.value).toEqual([{name: CONST.VIOLATIONS.SMARTSCAN_FAILED, type: CONST.VIOLATION_TYPES.WARNING, showInReview: true}]); + expect(result.value).toEqual( + expect.arrayContaining([{name: CONST.VIOLATIONS.SMARTSCAN_FAILED, type: CONST.VIOLATION_TYPES.WARNING, showInReview: true}, missingCategoryViolation]), + ); + }); + + it('should not add smartscanFailed when scan failed but required fields are filled', () => { + const transactionWithEnteredDetails = { + ...transaction, + amount: 10000, + merchant: 'Coffee Shop', + iouRequestType: CONST.IOU.REQUEST_TYPE.SCAN, + receipt: {state: CONST.IOU.RECEIPT_STATE.SCAN_FAILED}, + }; + const result = ViolationsUtils.getViolationsOnyxData(transactionWithEnteredDetails, transactionViolations, policy, policyTags, policyCategories, false, false); + expect(result.value).not.toContainEqual(expect.objectContaining({name: CONST.VIOLATIONS.SMARTSCAN_FAILED})); + }); + + it('should not add smartscanFailed when scan failed but modified fields are filled (amount and merchant)', () => { + const transactionWithModifiedDetails = { + ...transaction, + amount: 0, + modifiedAmount: 12345, + merchant: '', + modifiedMerchant: 'Manual Merchant', + iouRequestType: CONST.IOU.REQUEST_TYPE.SCAN, + receipt: {state: CONST.IOU.RECEIPT_STATE.SCAN_FAILED}, + }; + const result = ViolationsUtils.getViolationsOnyxData( + transactionWithModifiedDetails as unknown as Transaction, + transactionViolations, + policy, + policyTags, + policyCategories, + false, + false, + ); + expect(result.value).not.toContainEqual(expect.objectContaining({name: CONST.VIOLATIONS.SMARTSCAN_FAILED})); }); });