Skip to content

Commit

Permalink
Merge pull request #52478 from Expensify/revert-52431-revert-51893-io…
Browse files Browse the repository at this point in the history
…natan_moverbrworkspacechat

Revert "Revert "Move RBR to workspace chats instead of transaction threads""
  • Loading branch information
pecanoro authored Nov 13, 2024
2 parents cada9d4 + 811cbf4 commit 5f431ab
Show file tree
Hide file tree
Showing 14 changed files with 95 additions and 182 deletions.
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

0 comments on commit 5f431ab

Please sign in to comment.