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

Revert "Revert "Move RBR to workspace chats instead of transaction threads"" #52478

Merged
merged 3 commits into from
Nov 13, 2024
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
2 changes: 1 addition & 1 deletion src/components/LHNOptionsList/OptionRowLHNData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ function OptionRowLHNData({

const optionItemRef = useRef<OptionData>();

const shouldDisplayViolations = ReportUtils.shouldDisplayTransactionThreadViolations(fullReport, transactionViolations, parentReportAction);
const shouldDisplayViolations = ReportUtils.shouldDisplayViolationsRBRInLHN(fullReport, transactionViolations);
const shouldDisplayReportViolations = ReportUtils.isReportOwner(fullReport) && ReportUtils.hasReportViolations(reportID);

const optionItem = useMemo(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ function MoneyRequestPreviewContent({
const isOnHold = TransactionUtils.isOnHold(transaction);
const isSettlementOrApprovalPartial = !!iouReport?.pendingFields?.partial;
const isPartialHold = isSettlementOrApprovalPartial && isOnHold;
const hasViolations = TransactionUtils.hasViolation(transaction?.transactionID ?? '-1', transactionViolations);
const hasNoticeTypeViolations = TransactionUtils.hasNoticeTypeViolation(transaction?.transactionID ?? '-1', transactionViolations) && ReportUtils.isPaidGroupPolicy(iouReport);
const hasViolations = TransactionUtils.hasViolation(transaction?.transactionID ?? '-1', transactionViolations, true);
const hasNoticeTypeViolations = TransactionUtils.hasNoticeTypeViolation(transaction?.transactionID ?? '-1', transactionViolations, true) && ReportUtils.isPaidGroupPolicy(iouReport);
const hasFieldErrors = TransactionUtils.hasMissingSmartscanFields(transaction);
const isDistanceRequest = TransactionUtils.isDistanceRequest(transaction);
const isFetchingWaypointsFromServer = TransactionUtils.isFetchingWaypointsFromServer(transaction);
Expand Down
5 changes: 3 additions & 2 deletions src/components/ReportActionItem/ReportPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,9 @@ function ReportPreview({
const hasErrors =
(hasMissingSmartscanFields && !iouSettled) ||
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
ReportUtils.hasViolations(iouReportID, transactionViolations) ||
ReportUtils.hasWarningTypeViolations(iouReportID, transactionViolations) ||
ReportUtils.hasViolations(iouReportID, transactionViolations, true) ||
ReportUtils.hasNoticeTypeViolations(iouReportID, transactionViolations, true) ||
ReportUtils.hasWarningTypeViolations(iouReportID, transactionViolations, true) ||
(ReportUtils.isReportOwner(iouReport) && ReportUtils.hasReportViolations(iouReportID)) ||
ReportUtils.hasActionsWithErrors(iouReportID);
const lastThreeTransactionsWithReceipts = transactionsWithReceipts.slice(-3);
Expand Down
2 changes: 1 addition & 1 deletion src/libs/DebugUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ function getReasonForShowingRowInLHN(report: OnyxEntry<Report>, hasRBR = false):
return null;
}

const doesReportHaveViolations = ReportUtils.shouldShowViolations(report, transactionViolations);
const doesReportHaveViolations = ReportUtils.shouldDisplayViolationsRBRInLHN(report, transactionViolations);

const reason = ReportUtils.reasonForReportToBeInOptionList({
report,
Expand Down
2 changes: 1 addition & 1 deletion src/libs/OptionsListUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1704,7 +1704,7 @@ function getOptions(
// Filter out all the reports that shouldn't be displayed
const filteredReportOptions = options.reports.filter((option) => {
const report = option.item;
const doesReportHaveViolations = ReportUtils.shouldShowViolations(report, transactionViolations);
const doesReportHaveViolations = ReportUtils.shouldDisplayViolationsRBRInLHN(report, transactionViolations);

return ReportUtils.shouldReportBeInOptionList({
report,
Expand Down
90 changes: 30 additions & 60 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6320,65 +6320,53 @@ function shouldHideReport(report: OnyxEntry<Report>, currentReportId: string): b
}

/**
* Checks to see if a report's parentAction is an expense that contains a violation type of either violation or warning
* Should we display a RBR on the LHN on this report due to violations?
*/
function doesTransactionThreadHaveViolations(
report: OnyxInputOrEntry<Report>,
transactionViolations: OnyxCollection<TransactionViolation[]>,
parentReportAction: OnyxInputOrEntry<ReportAction>,
): boolean {
if (!ReportActionsUtils.isMoneyRequestAction(parentReportAction)) {
return false;
}
const {IOUTransactionID, IOUReportID} = ReportActionsUtils.getOriginalMessage(parentReportAction) ?? {};
if (!IOUTransactionID || !IOUReportID) {
function shouldDisplayViolationsRBRInLHN(report: OnyxEntry<Report>, transactionViolations: OnyxCollection<TransactionViolation[]>): boolean {
// We only show the RBR in the highest level, which is the workspace chat
if (!report || !isPolicyExpenseChat(report)) {
return false;
}
if (!isCurrentUserSubmitter(IOUReportID)) {
return false;
}
if (report?.stateNum !== CONST.REPORT.STATE_NUM.OPEN && report?.stateNum !== CONST.REPORT.STATE_NUM.SUBMITTED) {

// We only show the RBR to the submitter
if (!isCurrentUserSubmitter(report.reportID ?? '')) {
return false;
}
return (
TransactionUtils.hasViolation(IOUTransactionID, transactionViolations) ||
TransactionUtils.hasWarningTypeViolation(IOUTransactionID, transactionViolations) ||
(isPaidGroupPolicy(report) && TransactionUtils.hasModifiedAmountOrDateViolation(IOUTransactionID, transactionViolations))

// Get all potential reports, which are the ones that are:
// - Owned by the same user
// - Are either open or submitted
// - Belong to the same workspace
// And if any have a violation, then it should have a RBR
const allReports = Object.values(ReportConnection.getAllReports() ?? {}) as Report[];
const potentialReports = allReports.filter((r) => r.ownerAccountID === currentUserAccountID && (r.stateNum ?? 0) <= 1 && r.policyID === report.policyID);
return potentialReports.some(
(potentialReport) => hasViolations(potentialReport.reportID, transactionViolations) || hasWarningTypeViolations(potentialReport.reportID, transactionViolations),
);
}

/**
* Checks if we should display violation - we display violations when the expense has violation and it is not settled
* Checks to see if a report contains a violation
*/
function shouldDisplayTransactionThreadViolations(
report: OnyxEntry<Report>,
transactionViolations: OnyxCollection<TransactionViolation[]>,
parentReportAction: OnyxEntry<ReportAction>,
): boolean {
if (!ReportActionsUtils.isMoneyRequestAction(parentReportAction)) {
return false;
}
const {IOUReportID} = ReportActionsUtils.getOriginalMessage(parentReportAction) ?? {};
if (isSettled(IOUReportID) || isReportApproved(IOUReportID?.toString())) {
return false;
}
return doesTransactionThreadHaveViolations(report, transactionViolations, parentReportAction);
function hasViolations(reportID: string, transactionViolations: OnyxCollection<TransactionViolation[]>, shouldShowInReview?: boolean): boolean {
const transactions = reportsTransactions[reportID] ?? [];
return transactions.some((transaction) => TransactionUtils.hasViolation(transaction.transactionID, transactionViolations, shouldShowInReview));
}

/**
* Checks to see if a report contains a violation
* Checks to see if a report contains a violation of type `warning`
*/
function hasViolations(reportID: string, transactionViolations: OnyxCollection<TransactionViolation[]>): boolean {
function hasWarningTypeViolations(reportID: string, transactionViolations: OnyxCollection<TransactionViolation[]>, shouldShowInReview?: boolean): boolean {
const transactions = reportsTransactions[reportID] ?? [];
return transactions.some((transaction) => TransactionUtils.hasViolation(transaction.transactionID, transactionViolations));
return transactions.some((transaction) => TransactionUtils.hasWarningTypeViolation(transaction.transactionID, transactionViolations, shouldShowInReview));
}

/**
* Checks to see if a report contains a violation of type `warning`
* Checks to see if a report contains a violation of type `notice`
*/
function hasWarningTypeViolations(reportID: string, transactionViolations: OnyxCollection<TransactionViolation[]>): boolean {
function hasNoticeTypeViolations(reportID: string, transactionViolations: OnyxCollection<TransactionViolation[]>, shouldShowInReview?: boolean): boolean {
const transactions = reportsTransactions[reportID] ?? [];
return transactions.some((transaction) => TransactionUtils.hasWarningTypeViolation(transaction.transactionID, transactionViolations));
return transactions.some((transaction) => TransactionUtils.hasNoticeTypeViolation(transaction.transactionID, transactionViolations, shouldShowInReview));
}

function hasReportViolations(reportID: string) {
Expand All @@ -6400,23 +6388,6 @@ function shouldAdminsRoomBeVisible(report: OnyxEntry<Report>): boolean {
return true;
}

/**
* Check whether report has violations
*/
function shouldShowViolations(report: Report, transactionViolations: OnyxCollection<TransactionViolation[]>) {
const {parentReportID, parentReportActionID} = report ?? {};
const canGetParentReport = parentReportID && parentReportActionID && allReportActions;
if (!canGetParentReport) {
return false;
}
const parentReportActions = allReportActions ? allReportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReportID}`] ?? {} : {};
const parentReportAction = parentReportActions[parentReportActionID] ?? null;
if (!parentReportAction) {
return false;
}
return shouldDisplayTransactionThreadViolations(report, transactionViolations, parentReportAction);
}

type ReportErrorsAndReportActionThatRequiresAttention = {
errors: ErrorFields;
reportAction?: OnyxEntry<ReportAction>;
Expand Down Expand Up @@ -6499,7 +6470,7 @@ function hasReportErrorsOtherThanFailedReceipt(report: Report, doesReportHaveVio
let doesTransactionThreadReportHasViolations = false;
if (oneTransactionThreadReportID) {
const transactionReport = getReport(oneTransactionThreadReportID);
doesTransactionThreadReportHasViolations = !!transactionReport && shouldShowViolations(transactionReport, transactionViolations);
doesTransactionThreadReportHasViolations = !!transactionReport && shouldDisplayViolationsRBRInLHN(transactionReport, transactionViolations);
}
return (
doesTransactionThreadReportHasViolations ||
Expand Down Expand Up @@ -8493,7 +8464,6 @@ export {
chatIncludesConcierge,
createDraftTransactionAndNavigateToParticipantSelector,
doesReportBelongToWorkspace,
doesTransactionThreadHaveViolations,
findLastAccessedReport,
findSelfDMReportID,
formatReportLastMessageText,
Expand Down Expand Up @@ -8597,6 +8567,7 @@ export {
hasUpdatedTotal,
hasViolations,
hasWarningTypeViolations,
hasNoticeTypeViolations,
isActionCreator,
isAdminRoom,
isAdminsOnlyPostingRoom,
Expand Down Expand Up @@ -8698,7 +8669,7 @@ export {
shouldDisableRename,
shouldDisableThread,
shouldDisplayThreadReplies,
shouldDisplayTransactionThreadViolations,
shouldDisplayViolationsRBRInLHN,
shouldReportBeInOptionList,
shouldReportShowSubscript,
shouldShowFlagComment,
Expand Down Expand Up @@ -8746,7 +8717,6 @@ export {
buildOptimisticChangeFieldAction,
isPolicyRelatedReport,
hasReportErrorsOtherThanFailedReceipt,
shouldShowViolations,
getAllReportErrors,
getAllReportActionsErrorsAndReportActionThatRequiresAttention,
hasInvoiceReports,
Expand Down
21 changes: 5 additions & 16 deletions src/libs/SidebarUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ function getOrderedReportIDs(
return;
}
const parentReportAction = ReportActionsUtils.getReportAction(report?.parentReportID ?? '-1', report?.parentReportActionID ?? '-1');
const doesReportHaveViolations = ReportUtils.shouldShowViolations(report, transactionViolations);
const doesReportHaveViolations = ReportUtils.shouldDisplayViolationsRBRInLHN(report, transactionViolations);
const isHidden = ReportUtils.getReportNotificationPreference(report) === CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN;
const isFocused = report.reportID === currentReportId;
const hasErrorsOtherThanFailedReceipt = ReportUtils.hasReportErrorsOtherThanFailedReceipt(report, doesReportHaveViolations, transactionViolations);
Expand Down Expand Up @@ -239,22 +239,11 @@ function getReasonAndReportActionThatHasRedBrickRoad(
): ReasonAndReportActionThatHasRedBrickRoad | null {
const {errors, reportAction} = ReportUtils.getAllReportActionsErrorsAndReportActionThatRequiresAttention(report, reportActions);
const hasErrors = Object.keys(errors).length !== 0;
const oneTransactionThreadReportID = ReportActionsUtils.getOneTransactionThreadReportID(report.reportID, ReportActionsUtils.getAllReportActions(report.reportID));

if (oneTransactionThreadReportID) {
const oneTransactionThreadReport = ReportUtils.getReport(oneTransactionThreadReportID);

if (
ReportUtils.shouldDisplayTransactionThreadViolations(
oneTransactionThreadReport,
transactionViolations,
ReportActionsUtils.getAllReportActions(report.reportID)[oneTransactionThreadReport?.parentReportActionID ?? '-1'],
)
) {
return {
reason: CONST.RBR_REASONS.HAS_TRANSACTION_THREAD_VIOLATIONS,
};
}
if (ReportUtils.shouldDisplayViolationsRBRInLHN(report, transactionViolations)) {
return {
reason: CONST.RBR_REASONS.HAS_TRANSACTION_THREAD_VIOLATIONS,
};
}

if (hasErrors) {
Expand Down
33 changes: 14 additions & 19 deletions src/libs/TransactionUtils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -865,41 +865,37 @@ function isOnHoldByTransactionID(transactionID: string): boolean {
/**
* Checks if any violations for the provided transaction are of type 'violation'
*/
function hasViolation(transactionID: string, transactionViolations: OnyxCollection<TransactionViolations>): boolean {
function hasViolation(transactionID: string, transactionViolations: OnyxCollection<TransactionViolations>, showInReview?: boolean): boolean {
return !!transactionViolations?.[ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS + transactionID]?.some(
(violation: TransactionViolation) => violation.type === CONST.VIOLATION_TYPES.VIOLATION,
(violation: TransactionViolation) => violation.type === CONST.VIOLATION_TYPES.VIOLATION && (showInReview === undefined || showInReview === (violation.showInReview ?? false)),
);
}

/**
* Checks if any violations for the provided transaction are of type 'notice'
*/
function hasNoticeTypeViolation(transactionID: string, transactionViolations: OnyxCollection<TransactionViolation[]>): boolean {
return !!transactionViolations?.[ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS + transactionID]?.some((violation: TransactionViolation) => violation.type === CONST.VIOLATION_TYPES.NOTICE);
function hasNoticeTypeViolation(transactionID: string, 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)),
);
}

/**
* Checks if any violations for the provided transaction are of type 'warning'
*/
function hasWarningTypeViolation(transactionID: string, transactionViolations: OnyxCollection<TransactionViolation[]>): boolean {
const warningTypeViolations = transactionViolations?.[ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS + transactionID]?.filter(
(violation: TransactionViolation) => violation.type === CONST.VIOLATION_TYPES.WARNING,
);
function hasWarningTypeViolation(transactionID: string, transactionViolations: OnyxCollection<TransactionViolation[]>, showInReview?: boolean | null): boolean {
const violations = transactionViolations?.[ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS + transactionID];
const warningTypeViolations =
violations?.filter(
(violation: TransactionViolation) => violation.type === CONST.VIOLATION_TYPES.WARNING && (showInReview === null || showInReview === (violation.showInReview ?? false)),
) ?? [];

const hasOnlyDupeDetectionViolation = warningTypeViolations?.every((violation: TransactionViolation) => violation.name === CONST.VIOLATIONS.DUPLICATED_TRANSACTION);
if (!Permissions.canUseDupeDetection(allBetas ?? []) && hasOnlyDupeDetectionViolation) {
return false;
}

return !!warningTypeViolations && warningTypeViolations.length > 0;
}

/**
* Checks if any violations for the provided transaction are of modifiedAmount or modifiedDate
*/
function hasModifiedAmountOrDateViolation(transactionID: string, transactionViolations: OnyxCollection<TransactionViolation[]>): boolean {
return !!transactionViolations?.[ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS + transactionID]?.some(
(violation: TransactionViolation) => violation.name === CONST.VIOLATIONS.MODIFIED_AMOUNT || violation.name === CONST.VIOLATIONS.MODIFIED_DATE,
);
return warningTypeViolations.length > 0;
}

/**
Expand Down Expand Up @@ -1291,7 +1287,6 @@ export {
shouldShowBrokenConnectionViolation,
hasNoticeTypeViolation,
hasWarningTypeViolation,
hasModifiedAmountOrDateViolation,
isCustomUnitRateIDForP2P,
getRateID,
getTransaction,
Expand Down
12 changes: 2 additions & 10 deletions src/libs/WorkspacesSettingsUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,7 @@ const getBrickRoadForPolicy = (report: Report, altReportActions?: OnyxCollection
let doesReportContainErrors = Object.keys(reportErrors ?? {}).length !== 0 ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined;

if (!doesReportContainErrors) {
const parentReportActions = (altReportActions ?? allReportActions)?.[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report?.parentReportID}`];
const parentReportAction = parentReportActions?.[report?.parentReportActionID ?? '-1'];
const shouldDisplayViolations = ReportUtils.shouldDisplayTransactionThreadViolations(report, allTransactionViolations, parentReportAction);
const shouldDisplayViolations = ReportUtils.shouldDisplayViolationsRBRInLHN(report, allTransactionViolations);
const shouldDisplayReportViolations = ReportUtils.isReportOwner(report) && ReportUtils.hasReportViolations(report.reportID);
const hasViolations = shouldDisplayViolations || shouldDisplayReportViolations;
if (hasViolations) {
Expand All @@ -78,13 +76,7 @@ const getBrickRoadForPolicy = (report: Report, altReportActions?: OnyxCollection
if (oneTransactionThreadReportID && !doesReportContainErrors) {
const oneTransactionThreadReport = ReportUtils.getReport(oneTransactionThreadReportID);

if (
ReportUtils.shouldDisplayTransactionThreadViolations(
oneTransactionThreadReport,
allTransactionViolations,
reportActions[oneTransactionThreadReport?.parentReportActionID ?? '-1'],
)
) {
if (ReportUtils.shouldDisplayViolationsRBRInLHN(oneTransactionThreadReport, allTransactionViolations)) {
doesReportContainErrors = CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR;
}
}
Expand Down
Loading
Loading