Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: blank receipt holder when delete expense offline #54051

Merged
merged 6 commits into from
Dec 25, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
Original file line number Diff line number Diff line change
Expand Up @@ -74,20 +74,20 @@ function MoneyRequestPreviewContent({
const route = useRoute<PlatformStackRouteProp<TransactionDuplicateNavigatorParamList, typeof SCREENS.TRANSACTION_DUPLICATE.REVIEW>>();
const {shouldUseNarrowLayout} = useResponsiveLayout();
const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST);
const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID || '-1'}`);
const [chatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${chatReportID}`);
const [session] = useOnyx(ONYXKEYS.SESSION);
const [iouReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID || '-1'}`);
const [iouReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`);

const policy = PolicyUtils.getPolicy(iouReport?.policyID);
const isMoneyRequestAction = ReportActionsUtils.isMoneyRequestAction(action);
const transactionID = isMoneyRequestAction ? ReportActionsUtils.getOriginalMessage(action)?.IOUTransactionID : '-1';
const transactionID = isMoneyRequestAction ? ReportActionsUtils.getOriginalMessage(action)?.IOUTransactionID : undefined;
const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`);
const [walletTerms] = useOnyx(ONYXKEYS.WALLET_TERMS);
const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS);

const sessionAccountID = session?.accountID;
const managerID = iouReport?.managerID ?? -1;
const ownerAccountID = iouReport?.ownerAccountID ?? -1;
const managerID = iouReport?.managerID ?? CONST.DEFAULT_NUMBER_ID;
const ownerAccountID = iouReport?.ownerAccountID ?? CONST.DEFAULT_NUMBER_ID;
const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(chatReport);

const participantAccountIDs =
Expand Down Expand Up @@ -117,9 +117,9 @@ function MoneyRequestPreviewContent({
const isOnHold = TransactionUtils.isOnHold(transaction);
const isSettlementOrApprovalPartial = !!iouReport?.pendingFields?.partial;
const isPartialHold = isSettlementOrApprovalPartial && isOnHold;
const hasViolations = TransactionUtils.hasViolation(transaction?.transactionID ?? '-1', transactionViolations, true);
const hasNoticeTypeViolations = TransactionUtils.hasNoticeTypeViolation(transaction?.transactionID ?? '-1', transactionViolations, true) && ReportUtils.isPaidGroupPolicy(iouReport);
const hasWarningTypeViolations = TransactionUtils.hasWarningTypeViolation(transaction?.transactionID ?? '-1', transactionViolations, true);
const hasViolations = TransactionUtils.hasViolation(transaction?.transactionID, transactionViolations, true);
const hasNoticeTypeViolations = TransactionUtils.hasNoticeTypeViolation(transaction?.transactionID, transactionViolations, true) && ReportUtils.isPaidGroupPolicy(iouReport);
const hasWarningTypeViolations = TransactionUtils.hasWarningTypeViolation(transaction?.transactionID, transactionViolations, true);
const hasFieldErrors = TransactionUtils.hasMissingSmartscanFields(transaction);
const isDistanceRequest = TransactionUtils.isDistanceRequest(transaction);
const isFetchingWaypointsFromServer = TransactionUtils.isFetchingWaypointsFromServer(transaction);
Expand Down Expand Up @@ -155,8 +155,8 @@ function MoneyRequestPreviewContent({
const shouldShowHoldMessage = !(isSettled && !isSettlementOrApprovalPartial) && !!transaction?.comment?.hold;

const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params?.threadReportID}`);
const parentReportAction = ReportActionsUtils.getReportAction(report?.parentReportID ?? '', report?.parentReportActionID ?? '');
const reviewingTransactionID = ReportActionsUtils.isMoneyRequestAction(parentReportAction) ? ReportActionsUtils.getOriginalMessage(parentReportAction)?.IOUTransactionID ?? '-1' : '-1';
const parentReportAction = ReportActionsUtils.getReportAction(report?.parentReportID, report?.parentReportActionID);
const reviewingTransactionID = ReportActionsUtils.isMoneyRequestAction(parentReportAction) ? ReportActionsUtils.getOriginalMessage(parentReportAction)?.IOUTransactionID : undefined;

/*
Show the merchant for IOUs and expenses only if:
Expand Down Expand Up @@ -253,10 +253,10 @@ function MoneyRequestPreviewContent({
if (TransactionUtils.isPending(transaction)) {
return {shouldShow: true, messageIcon: Expensicons.CreditCardHourglass, messageDescription: translate('iou.transactionPending')};
}
if (TransactionUtils.shouldShowBrokenConnectionViolation(transaction?.transactionID ?? '-1', iouReport, policy)) {
if (TransactionUtils.shouldShowBrokenConnectionViolation(transaction?.transactionID, iouReport, policy)) {
return {shouldShow: true, messageIcon: Expensicons.Hourglass, messageDescription: translate('violations.brokenConnection530Error')};
}
if (TransactionUtils.hasPendingUI(transaction, TransactionUtils.getTransactionViolations(transaction?.transactionID ?? '-1', transactionViolations))) {
if (TransactionUtils.hasPendingUI(transaction, TransactionUtils.getTransactionViolations(transaction?.transactionID, transactionViolations))) {
return {shouldShow: true, messageIcon: Expensicons.Hourglass, messageDescription: translate('iou.pendingMatchWithCreditCard')};
}
return {shouldShow: false};
Expand Down Expand Up @@ -301,12 +301,8 @@ function MoneyRequestPreviewContent({
// Clear the draft before selecting a different expense to prevent merging fields from the previous expense
// (e.g., category, tag, tax) that may be not enabled/available in the new expense's policy.
Transaction.abandonReviewDuplicateTransactions();
const comparisonResult = TransactionUtils.compareDuplicateTransactionFields(
reviewingTransactionID,
transaction?.reportID ?? '',
transaction?.transactionID ?? reviewingTransactionID,
);
Transaction.setReviewDuplicatesKey({...comparisonResult.keep, duplicates, transactionID: transaction?.transactionID ?? '', reportID: transaction?.reportID});
const comparisonResult = TransactionUtils.compareDuplicateTransactionFields(reviewingTransactionID, transaction?.reportID, transaction?.transactionID ?? reviewingTransactionID);
Transaction.setReviewDuplicatesKey({...comparisonResult.keep, duplicates, transactionID: transaction?.transactionID, reportID: transaction?.reportID});

if ('merchant' in comparisonResult.change) {
Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_MERCHANT_PAGE.getRoute(route.params?.threadReportID, backTo));
Expand Down Expand Up @@ -349,11 +345,13 @@ function MoneyRequestPreviewContent({
!onPreviewPressed ? [styles.moneyRequestPreviewBox, containerStyles] : {},
]}
>
<ReportActionItemImages
images={receiptImages}
isHovered={isHovered || isScanning}
size={1}
/>
{!isDeleted && (
<ReportActionItemImages
images={receiptImages}
isHovered={isHovered || isScanning}
size={1}
/>
)}
{isEmptyObject(transaction) && !ReportActionsUtils.isMessageDeleted(action) && action.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE ? (
<MoneyRequestSkeletonView />
) : (
Expand Down
25 changes: 13 additions & 12 deletions src/components/ReportActionItem/ReportPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ function ReportPreview({
const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS);
const [userWallet] = useOnyx(ONYXKEYS.USER_WALLET);
const [invoiceReceiverPolicy] = useOnyx(
`${ONYXKEYS.COLLECTION.POLICY}${chatReport?.invoiceReceiver && 'policyID' in chatReport.invoiceReceiver ? chatReport.invoiceReceiver.policyID : -1}`,
`${ONYXKEYS.COLLECTION.POLICY}${chatReport?.invoiceReceiver && 'policyID' in chatReport.invoiceReceiver ? chatReport.invoiceReceiver.policyID : CONST.DEFAULT_NUMBER_ID}`,
);
const theme = useTheme();
const styles = useThemeStyles();
Expand Down Expand Up @@ -144,10 +144,10 @@ function ReportPreview({
const shouldDisableApproveButton = shouldShowApproveButton && !ReportUtils.isAllowedToApproveExpenseReport(iouReport);

const {nonHeldAmount, fullAmount, hasValidNonHeldAmount} = ReportUtils.getNonHeldAndFullAmount(iouReport, shouldShowPayButton);
const hasOnlyHeldExpenses = ReportUtils.hasOnlyHeldExpenses(iouReport?.reportID ?? '');
const hasHeldExpenses = ReportUtils.hasHeldExpenses(iouReport?.reportID ?? '');
const hasOnlyHeldExpenses = ReportUtils.hasOnlyHeldExpenses(iouReport?.reportID);
const hasHeldExpenses = ReportUtils.hasHeldExpenses(iouReport?.reportID);

const managerID = iouReport?.managerID ?? action.childManagerAccountID ?? 0;
const managerID = iouReport?.managerID ?? action.childManagerAccountID ?? CONST.DEFAULT_NUMBER_ID;
const {totalDisplaySpend, reimbursableSpend} = ReportUtils.getMoneyRequestSpendBreakdown(iouReport);

const iouSettled = ReportUtils.isSettled(iouReportID) || action?.childStatusNum === CONST.REPORT.STATUS_NUM.REIMBURSED;
Expand Down Expand Up @@ -189,9 +189,8 @@ function ReportPreview({
const lastThreeReceipts = lastThreeTransactions.map((transaction) => ({...ReceiptUtils.getThumbnailAndImageURIs(transaction), transaction}));
const showRTERViolationMessage =
numberOfRequests === 1 &&
TransactionUtils.hasPendingUI(allTransactions.at(0), TransactionUtils.getTransactionViolations(allTransactions.at(0)?.transactionID ?? '-1', transactionViolations));
const shouldShowBrokenConnectionViolation =
numberOfRequests === 1 && TransactionUtils.shouldShowBrokenConnectionViolation(allTransactions.at(0)?.transactionID ?? '-1', iouReport, policy);
TransactionUtils.hasPendingUI(allTransactions.at(0), TransactionUtils.getTransactionViolations(allTransactions.at(0)?.transactionID, transactionViolations));
const shouldShowBrokenConnectionViolation = numberOfRequests === 1 && TransactionUtils.shouldShowBrokenConnectionViolation(allTransactions.at(0)?.transactionID, iouReport, policy);
let formattedMerchant = numberOfRequests === 1 ? TransactionUtils.getMerchant(allTransactions.at(0)) : null;
const formattedDescription = numberOfRequests === 1 ? TransactionUtils.getDescription(allTransactions.at(0)) : null;

Expand Down Expand Up @@ -500,11 +499,13 @@ function ReportPreview({
accessibilityLabel={translate('iou.viewDetails')}
>
<View style={[styles.reportPreviewBox, isHovered || isScanning || isWhisper ? styles.reportPreviewBoxHoverBorder : undefined]}>
<ReportActionItemImages
images={lastThreeReceipts}
total={allTransactions.length}
size={CONST.RECEIPT.MAX_REPORT_PREVIEW_RECEIPTS}
/>
{lastThreeReceipts.length > 0 && (
<ReportActionItemImages
images={lastThreeReceipts}
total={allTransactions.length}
size={CONST.RECEIPT.MAX_REPORT_PREVIEW_RECEIPTS}
/>
)}
<View style={[styles.expenseAndReportPreviewBoxBody, hasReceipts ? styles.mtn1 : {}]}>
<View style={shouldShowSettlementButton ? {} : styles.expenseAndReportPreviewTextButtonContainer}>
<View style={styles.expenseAndReportPreviewTextContainer}>
Expand Down
4 changes: 2 additions & 2 deletions src/libs/ReportActionsUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -929,8 +929,8 @@ function getLinkedTransactionID(reportActionOrID: string | OnyxEntry<ReportActio
return getOriginalMessage(reportAction)?.IOUTransactionID ?? null;
}

function getReportAction(reportID: string, reportActionID: string): ReportAction | undefined {
return allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`]?.[reportActionID];
function getReportAction(reportID?: string, reportActionID?: string): ReportAction | undefined {
return reportActionID ? allReportActions?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`]?.[reportActionID] : undefined;
}

function getMostRecentReportActionLastModified(): string {
Expand Down
2 changes: 1 addition & 1 deletion src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7799,7 +7799,7 @@ function hasHeldExpenses(iouReportID?: string, allReportTransactions?: SearchTra
/**
* Check if all expenses in the Report are on hold
*/
function hasOnlyHeldExpenses(iouReportID: string, allReportTransactions?: SearchTransaction[]): boolean {
function hasOnlyHeldExpenses(iouReportID?: string, allReportTransactions?: SearchTransaction[]): boolean {
const reportTransactions = allReportTransactions ?? reportsTransactions[iouReportID ?? ''] ?? [];
return reportTransactions.length > 0 && !reportTransactions.some((transaction) => !TransactionUtils.isOnHold(transaction));
}
Expand Down
25 changes: 14 additions & 11 deletions src/libs/TransactionUtils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ function hasMissingSmartscanFields(transaction: OnyxInputOrEntry<Transaction>):
/**
* Get all transaction violations of the transaction with given tranactionID.
*/
function getTransactionViolations(transactionID: string, transactionViolations: OnyxCollection<TransactionViolations> | null): TransactionViolations | null {
function getTransactionViolations(transactionID: string | undefined, transactionViolations: OnyxCollection<TransactionViolations> | null): TransactionViolations | null {
return transactionViolations?.[ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS + transactionID] ?? null;
}

Expand All @@ -723,7 +723,7 @@ function hasPendingRTERViolation(transactionViolations?: TransactionViolations |
/**
* Check if there is broken connection violation.
*/
function hasBrokenConnectionViolation(transactionID: string): boolean {
function hasBrokenConnectionViolation(transactionID?: string): boolean {
const violations = getTransactionViolations(transactionID, allTransactionViolations);
return !!violations?.find(
(violation) =>
Expand All @@ -735,7 +735,7 @@ function hasBrokenConnectionViolation(transactionID: string): boolean {
/**
* Check if user should see broken connection violation warning.
*/
function shouldShowBrokenConnectionViolation(transactionID: string, report: OnyxEntry<Report> | SearchReport, policy: OnyxEntry<Policy> | SearchPolicy): boolean {
function shouldShowBrokenConnectionViolation(transactionID: string | undefined, report: OnyxEntry<Report> | SearchReport, policy: OnyxEntry<Policy> | SearchPolicy): boolean {
return (
hasBrokenConnectionViolation(transactionID) &&
(!PolicyUtils.isPolicyAdmin(policy) || ReportUtils.isOpenExpenseReport(report) || (ReportUtils.isProcessingReport(report) && PolicyUtils.isInstantSubmitEnabled(policy)))
Expand Down Expand Up @@ -881,7 +881,7 @@ function isOnHoldByTransactionID(transactionID: string): boolean {
/**
* Checks if any violations for the provided transaction are of type 'violation'
*/
function hasViolation(transactionID: string, transactionViolations: OnyxCollection<TransactionViolations>, showInReview?: boolean): boolean {
function hasViolation(transactionID: string | undefined, transactionViolations: OnyxCollection<TransactionViolations>, showInReview?: boolean): boolean {
return !!transactionViolations?.[ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS + transactionID]?.some(
(violation: TransactionViolation) => violation.type === CONST.VIOLATION_TYPES.VIOLATION && (showInReview === undefined || showInReview === (violation.showInReview ?? false)),
);
Expand All @@ -890,7 +890,7 @@ function hasViolation(transactionID: string, transactionViolations: OnyxCollecti
/**
* Checks if any violations for the provided transaction are of type 'notice'
*/
function hasNoticeTypeViolation(transactionID: string, transactionViolations: OnyxCollection<TransactionViolation[]>, showInReview?: boolean): boolean {
function hasNoticeTypeViolation(transactionID: string | undefined, transactionViolations: OnyxCollection<TransactionViolation[]>, showInReview?: boolean): boolean {
return !!transactionViolations?.[ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS + transactionID]?.some(
(violation: TransactionViolation) => violation.type === CONST.VIOLATION_TYPES.NOTICE && (showInReview === undefined || showInReview === (violation.showInReview ?? false)),
);
Expand All @@ -899,7 +899,7 @@ function hasNoticeTypeViolation(transactionID: string, transactionViolations: On
/**
* Checks if any violations for the provided transaction are of type 'warning'
*/
function hasWarningTypeViolation(transactionID: string, transactionViolations: OnyxCollection<TransactionViolation[]>, showInReview?: boolean): boolean {
function hasWarningTypeViolation(transactionID: string | undefined, transactionViolations: OnyxCollection<TransactionViolation[]>, showInReview?: boolean): boolean {
const violations = transactionViolations?.[ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS + transactionID];
const warningTypeViolations =
violations?.filter(
Expand Down Expand Up @@ -1060,21 +1060,24 @@ function removeSettledAndApprovedTransactions(transactionIDs: string[]) {
*/

function compareDuplicateTransactionFields(
reviewingTransactionID: string | undefined,
reportID: string | undefined,
reviewingTransactionID?: string | undefined,
reportID?: string | undefined,
selectedTransactionID?: string,
): {keep: Partial<ReviewDuplicates>; change: FieldsToChange} {
if (!reviewingTransactionID || !reportID) {
return {change: {}, keep: {}};
}

const transactionViolations = allTransactionViolations?.[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${reviewingTransactionID}`];
const duplicates = transactionViolations?.find((violation) => violation.name === CONST.VIOLATIONS.DUPLICATED_TRANSACTION)?.data?.duplicates ?? [];
const transactions = removeSettledAndApprovedTransactions([reviewingTransactionID, ...duplicates]).map((item) => getTransaction(item));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const keep: Record<string, any> = {};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const change: Record<string, any[]> = {};
if (!reviewingTransactionID || !reportID) {
return {keep, change};
}
const transactionViolations = allTransactionViolations?.[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${reviewingTransactionID}`];
const duplicates = transactionViolations?.find((violation) => violation.name === CONST.VIOLATIONS.DUPLICATED_TRANSACTION)?.data?.duplicates ?? [];
const transactions = removeSettledAndApprovedTransactions([reviewingTransactionID, ...duplicates]).map((item) => getTransaction(item));

const fieldsToCompare: FieldsToCompare = {
merchant: ['modifiedMerchant', 'merchant'],
Expand Down
Loading