Skip to content
Merged
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
8 changes: 5 additions & 3 deletions src/components/MoneyRequestConfirmationList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ function MoneyRequestConfirmationList({
const [policyCategoriesReal] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`, {canBeMissing: true});
const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, {canBeMissing: true});
const [policyReal] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {canBeMissing: true});
const [transactionReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transaction?.reportID}`, {canBeMissing: true});
const [policyDraft] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_DRAFTS}${policyID}`, {canBeMissing: true});
const [defaultMileageRateDraft] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_DRAFTS}${policyID}`, {
selector: mileageRateSelector,
Expand Down Expand Up @@ -412,8 +413,8 @@ function MoneyRequestConfirmationList({
return false;
}

return (!!hasSmartScanFailed && hasMissingSmartscanFields(transaction)) || (didConfirmSplit && areRequiredFieldsEmpty(transaction));
}, [isEditingSplitBill, hasSmartScanFailed, transaction, didConfirmSplit]);
return (!!hasSmartScanFailed && hasMissingSmartscanFields(transaction, transactionReport)) || (didConfirmSplit && areRequiredFieldsEmpty(transaction, transactionReport));
}, [isEditingSplitBill, hasSmartScanFailed, transaction, didConfirmSplit, transactionReport]);

const isMerchantEmpty = useMemo(() => !iouMerchant || isMerchantMissing(transaction), [transaction, iouMerchant]);
const isMerchantRequired = isPolicyExpenseChat && (!isScanRequest || isEditingSplitBill) && shouldShowMerchant;
Expand Down Expand Up @@ -970,7 +971,7 @@ function MoneyRequestConfirmationList({
}
}

if (isEditingSplitBill && areRequiredFieldsEmpty(transaction)) {
if (isEditingSplitBill && areRequiredFieldsEmpty(transaction, transactionReport)) {
setDidConfirmSplit(true);
setFormError('iou.error.genericSmartscanFailureMessage');
return;
Expand Down Expand Up @@ -1028,6 +1029,7 @@ function MoneyRequestConfirmationList({
showDelegateNoAccessModal,
iouCategory,
policyCategories,
transactionReport,
iouAttendees,
currentUserPersonalDetails,
],
Expand Down
3 changes: 2 additions & 1 deletion src/components/ReportActionItem/MoneyRequestView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ function MoneyRequestView({
const companyCardPageURL = `${environmentURL}/${ROUTES.WORKSPACE_COMPANY_CARDS.getRoute(transactionThreadReport?.policyID)}`;
const [originalTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${getNonEmptyStringOnyxID(transaction?.comment?.originalTransactionID)}`, {canBeMissing: true});
const {isExpenseSplit} = getOriginalTransactionWithSplitInfo(transaction, originalTransaction);
const [transactionReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transaction?.reportID}`, {canBeMissing: true});
const isSplitAvailable = moneyRequestReport && transaction && isSplitAction(moneyRequestReport, [transaction], originalTransaction, currentUserPersonalDetails.login ?? '', policy);

const canEditTaxFields = canEdit && !isDistanceRequest;
Expand Down Expand Up @@ -511,7 +512,7 @@ function MoneyRequestView({
rateToDisplay = getRateFromMerchant(updatedMerchantTitle);
}

const hasErrors = hasMissingSmartscanFields(transaction);
const hasErrors = hasMissingSmartscanFields(transaction, transactionReport);
const isMissingAttendeesViolation = getIsMissingAttendeesViolation(
policyCategories,
updatedTransaction?.category ?? categoryForDisplay,
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useShowNotFoundPageInIOUStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const useShowNotFoundPageInIOUStep = (action: IOUAction, iouType: IOUType, repor

// eslint-disable-next-line rulesdir/no-negated-variables
let shouldShowNotFoundPage = false;
const canEditSplitBill = isSplitBill && reportAction && session?.accountID === reportAction.actorAccountID && areRequiredFieldsEmpty(transaction);
const canEditSplitBill = isSplitBill && reportAction && session?.accountID === reportAction.actorAccountID && areRequiredFieldsEmpty(transaction, iouReport);
const canEditSplitExpense = isSplitExpense && !!transaction;

if (isEditing) {
Expand Down
42 changes: 15 additions & 27 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4960,19 +4960,10 @@ function getLinkedTransaction(reportAction: OnyxEntry<ReportAction | OptimisticI
return transactions ? transactions.find((transaction) => transaction.transactionID === transactionID) : allTransactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`];
}

/**
* Check if any of the transactions in the report has required missing fields
*/
function hasMissingSmartscanFields(iouReportID: string | undefined, transactions?: Transaction[]): boolean {
const reportTransactions = transactions ?? getReportTransactions(iouReportID);

return reportTransactions.some((transaction) => hasMissingSmartscanFieldsTransactionUtils(transaction));
}

/**
* Get report action which is missing smartscan fields
*/
function getReportActionWithMissingSmartscanFields(iouReportID: string | undefined): ReportAction | undefined {
function getReportActionWithMissingSmartscanFields(report: OnyxEntry<Report>, iouReportID: string | undefined): ReportAction | undefined {
const reportActions = Object.values(getAllReportActions(iouReportID));
return reportActions.find((action) => {
if (!isMoneyRequestAction(action)) {
Expand All @@ -4985,15 +4976,15 @@ function getReportActionWithMissingSmartscanFields(iouReportID: string | undefin
if (!wasActionTakenByCurrentUser(action)) {
return false;
}
return hasMissingSmartscanFieldsTransactionUtils(transaction);
return hasMissingSmartscanFieldsTransactionUtils(transaction, report);
});
}

/**
* Check if iouReportID has required missing fields
*/
function shouldShowRBRForMissingSmartscanFields(iouReportID: string | undefined): boolean {
return !!getReportActionWithMissingSmartscanFields(iouReportID);
function shouldShowRBRForMissingSmartscanFields(report: OnyxEntry<Report>, iouReportID: string | undefined): boolean {
return !!getReportActionWithMissingSmartscanFields(report, iouReportID);
}

/**
Expand Down Expand Up @@ -5031,7 +5022,8 @@ function getTransactionReportName({
return translateLocal('iou.receiptScanning', {count: 1});
}

if (hasMissingSmartscanFieldsTransactionUtils(transaction)) {
const report = getReportOrDraftReport(transaction?.reportID, reports);
if (hasMissingSmartscanFieldsTransactionUtils(transaction, report)) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
return translateLocal('iou.receiptMissingDetails');
}
Expand All @@ -5045,7 +5037,6 @@ function getTransactionReportName({
return getIOUReportActionDisplayMessage(reportAction as ReportAction, transaction);
}

const report = getReportOrDraftReport(transaction?.reportID, reports);
const amount = getTransactionAmount(transaction, !isEmptyObject(report) && isExpenseReport(report), transaction?.reportID === CONST.REPORT.UNREPORTED_REPORT_ID) ?? 0;
const formattedAmount = convertToDisplayString(amount, getCurrency(transaction)) ?? '';
const comment = getMerchantOrDescription(transaction);
Expand Down Expand Up @@ -5103,7 +5094,7 @@ function getReportPreviewMessage(
return translateLocal('iou.receiptScanning', {count: 1});
}

if (hasMissingSmartscanFieldsTransactionUtils(linkedTransaction)) {
if (hasMissingSmartscanFieldsTransactionUtils(linkedTransaction, report)) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
return translateLocal('iou.receiptMissingDetails');
}
Expand Down Expand Up @@ -5139,7 +5130,7 @@ function getReportPreviewMessage(
return translateLocal('iou.receiptScanning', {count: 1});
}

if (hasMissingSmartscanFieldsTransactionUtils(linkedTransaction)) {
if (hasMissingSmartscanFieldsTransactionUtils(linkedTransaction, report)) {
// eslint-disable-next-line @typescript-eslint/no-deprecated
return translateLocal('iou.receiptMissingDetails');
}
Expand Down Expand Up @@ -9321,9 +9312,9 @@ function getAllReportActionsErrorsAndReportActionThatRequiresAttention(
}
}

if (!isReportArchived && hasSmartscanError(reportActionsArray)) {
if (!isReportArchived && hasSmartscanError(reportActionsArray, report)) {
reportActionErrors.smartscan = getMicroSecondOnyxErrorWithTranslationKey('iou.error.genericSmartscanFailureMessage');
reportAction = getReportActionWithSmartscanError(reportActionsArray);
reportAction = getReportActionWithSmartscanError(reportActionsArray, report);
}

if (!isReportArchived && report?.statusNum === CONST.REPORT.STATUS_NUM.OPEN) {
Expand Down Expand Up @@ -10611,22 +10602,22 @@ function canEditReportDescription(report: OnyxEntry<Report>, policy: OnyxEntry<P
);
}

function getReportActionWithSmartscanError(reportActions: ReportAction[]): ReportAction | undefined {
function getReportActionWithSmartscanError(reportActions: ReportAction[], report: OnyxEntry<Report>): ReportAction | undefined {
return reportActions.find((action) => {
const isReportPreview = isReportPreviewAction(action);
const isSplitOrTrackAction = isSplitBillReportAction(action) || isTrackExpenseAction(action);
if (!isSplitOrTrackAction && !isReportPreview) {
return false;
}
const IOUReportID = getIOUReportIDFromReportActionPreview(action);
const isReportPreviewError = isReportPreview && shouldShowRBRForMissingSmartscanFields(IOUReportID) && !isSettled(IOUReportID);
const isReportPreviewError = isReportPreview && shouldShowRBRForMissingSmartscanFields(report, IOUReportID) && !isSettled(IOUReportID);
if (isReportPreviewError) {
return true;
}

const transactionID = isSplitOrTrackAction ? getOriginalMessage(action)?.IOUTransactionID : undefined;
const transaction = allTransactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`] ?? {};
const isTransactionThreadError = isSplitOrTrackAction && hasMissingSmartscanFieldsTransactionUtils(transaction as Transaction);
const isTransactionThreadError = isSplitOrTrackAction && hasMissingSmartscanFieldsTransactionUtils(transaction as Transaction, report);

return isTransactionThreadError;
});
Expand All @@ -10635,8 +10626,8 @@ function getReportActionWithSmartscanError(reportActions: ReportAction[]): Repor
/**
* Checks if report action has error when smart scanning
*/
function hasSmartscanError(reportActions: ReportAction[]): boolean {
return !!getReportActionWithSmartscanError(reportActions);
function hasSmartscanError(reportActions: ReportAction[], report: OnyxEntry<Report>): boolean {
return !!getReportActionWithSmartscanError(reportActions, report);
}

function shouldAutoFocusOnKeyPress(event: KeyboardEvent): boolean {
Expand Down Expand Up @@ -13086,7 +13077,6 @@ export {
hasHeldExpenses,
hasIOUWaitingOnCurrentUserBankAccount,
hasMissingPaymentMethod,
hasMissingSmartscanFields,
hasNonReimbursableTransactions,
hasOnlyHeldExpenses,
hasOnlyTransactionsWithPendingRoutes,
Expand Down Expand Up @@ -13218,8 +13208,6 @@ export {
shouldReportShowSubscript,
shouldShowFlagComment,
sortOutstandingReportsBySelected,
getReportActionWithMissingSmartscanFields,
shouldShowRBRForMissingSmartscanFields,
shouldUseFullTitleToDisplay,
updateOptimisticParentReportAction,
updateReportPreview,
Expand Down
8 changes: 4 additions & 4 deletions src/libs/TransactionPreviewUtils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import truncate from 'lodash/truncate';
import type {OnyxEntry, OnyxInputValue} from 'react-native-onyx';
import type {OnyxEntry} from 'react-native-onyx';
import CONST from '@src/CONST';
import type {TranslationPaths} from '@src/languages/types';
import ROUTES from '@src/ROUTES';
Expand Down Expand Up @@ -215,7 +215,7 @@ function getTransactionPreviewTextAndTranslationPaths({
const shouldShowHoldMessage = !(isMoneyRequestSettled && !isSettlementOrApprovalPartial) && !!transaction?.comment?.hold;
const showCashOrCard: TranslationPathOrText = {translationPath: isTransactionMadeWithCard ? 'iou.card' : 'iou.cash'};
const isTransactionScanning = isScanning(transaction);
const hasFieldErrors = hasMissingSmartscanFields(transaction);
const hasFieldErrors = hasMissingSmartscanFields(transaction, iouReport);
const isPaidGroupPolicy = isPaidGroupPolicyUtil(iouReport);

// This will be fixed as part of https://github.com/Expensify/Expensify/issues/507850
Expand Down Expand Up @@ -363,7 +363,7 @@ function createTransactionPreviewConditionals({
currentUserAccountID,
reportActions,
}: {
iouReport: OnyxInputValue<OnyxTypes.Report> | undefined;
iouReport: OnyxEntry<OnyxTypes.Report>;
transaction: OnyxEntry<OnyxTypes.Transaction> | undefined;
action: OnyxEntry<OnyxTypes.ReportAction>;
violations: OnyxTypes.TransactionViolations;
Expand All @@ -389,7 +389,7 @@ function createTransactionPreviewConditionals({
const policy = getPolicy(iouReport?.policyID);
const hasViolationsOfTypeNotice =
hasNoticeTypeViolation(transaction, violations, currentUserEmail ?? '', currentUserAccountID, iouReport ?? undefined, policy, true) && iouReport && isPaidGroupPolicyUtil(iouReport);
const hasFieldErrors = hasMissingSmartscanFields(transaction);
const hasFieldErrors = hasMissingSmartscanFields(transaction, iouReport);

const isFetchingWaypoints = isFetchingWaypointsFromServer(transaction);

Expand Down
26 changes: 6 additions & 20 deletions src/libs/TransactionUtils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,15 +137,6 @@ Onyx.connectWithoutView({
callback: (value) => (allBetas = value),
});

let deprecatedAllReports: OnyxCollection<Report> = {};
Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (value) => {
deprecatedAllReports = value;
},
});

function hasDistanceCustomUnit(transaction: OnyxEntry<Transaction> | Partial<Transaction>): boolean {
const type = transaction?.comment?.type;
const customUnitName = transaction?.comment?.customUnit?.name;
Expand Down Expand Up @@ -579,17 +570,12 @@ function isCreatedMissing(transaction: OnyxEntry<Transaction>) {
return transaction?.created === '' && (!transaction.created || transaction.modifiedCreated === '');
}

function areRequiredFieldsEmpty(transaction: OnyxEntry<Transaction>, reportTransaction?: OnyxEntry<Report>): boolean {
const parentReport = reportTransaction ?? deprecatedAllReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transaction?.reportID}`];
const isFromExpenseReport = parentReport?.type === CONST.REPORT.TYPE.EXPENSE;
const isSplitPolicyExpenseChat = !!transaction?.comment?.splits?.some(
(participant) => deprecatedAllReports?.[`${ONYXKEYS.COLLECTION.REPORT}${participant.chatReportID}`]?.isOwnPolicyExpenseChat,
);
Comment on lines -585 to -587
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was added in this PR, but it looks outdated and safe to remove now

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DylanDylann Why is this not required now?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While implementing the PR, I rechecked why isSplitPolicyExpenseChat was added and found the context in #37740. Since the split flow has changed, and on staging we now allow splitting even when the request is missing a merchant, so I removed that logic.

const isMerchantRequired = isFromExpenseReport || isSplitPolicyExpenseChat;
function areRequiredFieldsEmpty(transaction: OnyxEntry<Transaction>, transactionReport: OnyxEntry<Report>): boolean {
const isFromExpenseReport = transactionReport?.type === CONST.REPORT.TYPE.EXPENSE;
if (Permissions.isBetaEnabled(CONST.BETAS.ZERO_EXPENSES, allBetas)) {
return (isMerchantRequired && isMerchantMissing(transaction)) || isCreatedMissing(transaction);
return (isFromExpenseReport && isMerchantMissing(transaction)) || isCreatedMissing(transaction);
}
return (isMerchantRequired && isMerchantMissing(transaction)) || isAmountMissing(transaction) || isCreatedMissing(transaction);
return (isFromExpenseReport && isMerchantMissing(transaction)) || isAmountMissing(transaction) || isCreatedMissing(transaction);
}

function getClearedPendingFields(transactionChanges: TransactionChanges) {
Expand Down Expand Up @@ -1407,8 +1393,8 @@ function didReceiptScanSucceed(transaction: OnyxEntry<Transaction>): boolean {
/**
* Check if the transaction has a non-smart-scanning receipt and is missing required fields
*/
function hasMissingSmartscanFields(transaction: OnyxInputOrEntry<Transaction>, reportTransaction?: OnyxEntry<Report>): boolean {
return !!(transaction && !isDistanceRequest(transaction) && !isReceiptBeingScanned(transaction) && areRequiredFieldsEmpty(transaction, reportTransaction));
function hasMissingSmartscanFields(transaction: OnyxInputOrEntry<Transaction>, transactionReport: OnyxEntry<Report>): boolean {
return !!(transaction && !isDistanceRequest(transaction) && !isReceiptBeingScanned(transaction) && areRequiredFieldsEmpty(transaction, transactionReport));
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/libs/Violations/ViolationsUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ const ViolationsUtils = {
hasDependentTags: boolean,
isInvoiceTransaction: boolean,
isSelfDM?: boolean,
iouReport?: OnyxEntry<Report> | null,
iouReport?: OnyxEntry<Report>,
isFromExpenseReport?: boolean,
): OnyxUpdate<typeof ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS> {
const isScanning = TransactionUtils.isScanning(updatedTransaction);
Expand Down Expand Up @@ -264,7 +264,7 @@ const ViolationsUtils = {
const shouldShowSmartScanFailedError =
isScanRequest &&
updatedTransaction.receipt?.state === CONST.IOU.RECEIPT_STATE.SCAN_FAILED &&
TransactionUtils.hasMissingSmartscanFields(updatedTransaction, iouReport ?? undefined) &&
TransactionUtils.hasMissingSmartscanFields(updatedTransaction, iouReport) &&
!hasUserStartedFixingSmartscan;
const hasSmartScanFailedError = transactionViolations.some((violation) => violation.name === CONST.VIOLATIONS.SMARTSCAN_FAILED);
if (shouldShowSmartScanFailedError && !hasSmartScanFailedError) {
Expand Down
3 changes: 2 additions & 1 deletion src/pages/iou/SplitBillDetailsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ function SplitBillDetailsPage({route, report, reportAction}: SplitBillDetailsPag
const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${getNonEmptyStringOnyxID(IOUTransactionID)}`, {canBeMissing: true});
const [draftTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${IOUTransactionID}`, {canBeMissing: true});
const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: true});
const [transactionReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transaction?.reportID}`, {canBeMissing: true});
const [quickAction] = useOnyx(ONYXKEYS.NVP_QUICK_ACTION_GLOBAL_CREATE, {canBeMissing: true});
const [session] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: false});
const [reportAttributesDerived] = useOnyx(ONYXKEYS.DERIVED.REPORT_ATTRIBUTES, {canBeMissing: true, selector: reportsSelector});
Expand All @@ -73,7 +74,7 @@ function SplitBillDetailsPage({route, report, reportAction}: SplitBillDetailsPag
const hasSmartScanFailed = hasReceipt(transaction) && transaction?.receipt?.state === CONST.IOU.RECEIPT_STATE.SCAN_FAILED;
const isDistanceRequest = isDistanceRequestUtil(transaction);
const isEditingSplitBill =
session?.accountID === actorAccountID && (areRequiredFieldsEmpty(transaction) || (transaction?.amount === 0 && !hasReceipt(transaction))) && !isDistanceRequest;
session?.accountID === actorAccountID && (areRequiredFieldsEmpty(transaction, transactionReport) || (transaction?.amount === 0 && !hasReceipt(transaction))) && !isDistanceRequest;
const isManualDistanceRequest = isManualDistanceRequestUtil(transaction);
const isMapDistanceRequest = isDistanceRequest && !isManualDistanceRequest;
const [isConfirmed, setIsConfirmed] = useState(false);
Expand Down
Loading
Loading