diff --git a/src/CONST/index.ts b/src/CONST/index.ts
index 2f6a44e6b552..7fbb6973ba6d 100644
--- a/src/CONST/index.ts
+++ b/src/CONST/index.ts
@@ -6703,6 +6703,7 @@ const CONST = {
RTER_VIOLATION_TYPES: {
BROKEN_CARD_CONNECTION: 'brokenCardConnection',
BROKEN_CARD_CONNECTION_530: 'brokenCardConnection530',
+ BROKEN_CARD_CONNECTION_531: 'brokenCardConnection531',
BROKEN_CARD_CONNECTION_REAUTH: 'brokenCardConnectionReauth',
SEVEN_DAY_HOLD: 'sevenDayHold',
},
diff --git a/src/components/BrokenConnectionDescription.tsx b/src/components/BrokenConnectionDescription.tsx
index 453a26247867..56a665ae900d 100644
--- a/src/components/BrokenConnectionDescription.tsx
+++ b/src/components/BrokenConnectionDescription.tsx
@@ -32,12 +32,13 @@ function BrokenConnectionDescription({transactionID, policy, report}: BrokenConn
const {environmentURL} = useEnvironment();
const brokenConnection530Error = transactionViolations?.find((violation) => violation.data?.rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530);
+ const brokenConnection531Error = transactionViolations?.find((violation) => violation.data?.rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_531);
const brokenConnectionReauthError = transactionViolations?.find((violation) => violation.data?.rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_REAUTH);
const brokenConnectionError = transactionViolations?.find((violation) => violation.data?.rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION);
const isPolicyAdmin = isPolicyAdminPolicyUtils(policy);
const workspaceCompanyCardRoute = `${environmentURL}/${ROUTES.WORKSPACE_COMPANY_CARDS.getRoute(policy?.id)}`;
- if (!brokenConnection530Error && !brokenConnectionReauthError && !brokenConnectionError) {
+ if (!brokenConnection530Error && !brokenConnection531Error && !brokenConnectionReauthError && !brokenConnectionError) {
return '';
}
@@ -45,6 +46,10 @@ function BrokenConnectionDescription({transactionID, policy, report}: BrokenConn
return translate('violations.brokenConnection530Error');
}
+ if (brokenConnection531Error) {
+ return translate('violations.brokenConnection531Error');
+ }
+
const isReauth = !!brokenConnectionReauthError;
const adminErrorKey = isReauth ? 'violations.adminReauthConnectionError' : 'violations.adminBrokenConnectionError';
const memberErrorKey = isReauth ? 'violations.memberReauthConnectionError' : 'violations.memberBrokenConnectionError';
diff --git a/src/components/MoneyReportHeaderStatusBarSection.tsx b/src/components/MoneyReportHeaderStatusBarSection.tsx
index 8ffa564fab29..88042714ac4f 100644
--- a/src/components/MoneyReportHeaderStatusBarSection.tsx
+++ b/src/components/MoneyReportHeaderStatusBarSection.tsx
@@ -6,6 +6,7 @@ import useTransactionsAndViolationsForReport from '@hooks/useTransactionsAndViol
import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
import {isProcessingReport} from '@libs/ReportUtils';
+import {getUnsuppressibleBrokenConnectionTransactionID} from '@libs/TransactionUtils';
import variables from '@styles/variables';
@@ -33,8 +34,9 @@ function MoneyReportHeaderStatusBarSection({reportID, statusBarType, iouTransact
const [moneyRequestReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`);
const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${getNonEmptyStringOnyxID(moneyRequestReport?.policyID)}`);
+ const [cardList] = useOnyx(ONYXKEYS.CARD_LIST);
- const {transactions: reportTransactionsMap} = useTransactionsAndViolationsForReport(moneyRequestReport?.reportID);
+ const {transactions: reportTransactionsMap, violations} = useTransactionsAndViolationsForReport(moneyRequestReport?.reportID);
const transactions = Object.values(reportTransactionsMap);
const expensifyIcons = useMemoizedLazyExpensifyIcons(['Hourglass', 'Box', 'Stopwatch', 'Flag', 'CreditCardHourglass', 'ReceiptScan']);
@@ -98,7 +100,9 @@ function MoneyReportHeaderStatusBarSection({reportID, statusBarType, iouTransact
}
if (statusBarType === CONST.REPORT.STATUS_BAR_TYPE.BROKEN_CONNECTION) {
- if (!iouTransactionID) {
+ // A multi-expense report has no single transaction, so use one whose broken connection cannot be suppressed.
+ const brokenConnectionTransactionID = iouTransactionID ?? getUnsuppressibleBrokenConnectionTransactionID(transactions, violations, cardList);
+ if (!brokenConnectionTransactionID) {
return null;
}
return (
@@ -106,7 +110,7 @@ function MoneyReportHeaderStatusBarSection({reportID, statusBarType, iouTransact
icon={getStatusIcon(expensifyIcons.Hourglass)}
description={
diff --git a/src/components/MoneyRequestHeader.tsx b/src/components/MoneyRequestHeader.tsx
index 915ae005b74c..25f5c06d9028 100644
--- a/src/components/MoneyRequestHeader.tsx
+++ b/src/components/MoneyRequestHeader.tsx
@@ -9,7 +9,6 @@ import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import useTransactionViolations from '@hooks/useTransactionViolations';
-import {isPersonalCard} from '@libs/CardUtils';
import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types';
import type {ReportsSplitNavigatorParamList, RightModalNavigatorParamList} from '@libs/Navigation/types';
@@ -17,12 +16,13 @@ import {getOriginalMessage, isMoneyRequestAction} from '@libs/ReportActionsUtils
import {isMarkAsResolvedAction} from '@libs/ReportPrimaryActionUtils';
import {isSelfDM, isSettled as isSettledReportUtils} from '@libs/ReportUtils';
import {
- getBrokenConnectionViolation,
hasPendingRTERViolation as hasPendingRTERViolationTransactionUtils,
+ isBrokenConnectionViolation,
isDuplicate as isDuplicateTransactionUtils,
isOnHold as isOnHoldTransactionUtils,
isPending,
isScanning,
+ shouldSuppressBrokenConnectionStatus,
shouldShowBrokenConnectionViolation as shouldShowBrokenConnectionViolationTransactionUtils,
} from '@libs/TransactionUtils';
@@ -129,14 +129,11 @@ function MoneyRequestHeader({reportID: reportIDProp, onBackButtonPress}: MoneyRe
return {icon: getStatusIcon(icons.CreditCardHourglass), description: translate('iou.transactionPendingDescription')};
}
if (!!transaction?.transactionID && !!transactionViolations.length && shouldShowBrokenConnectionViolation) {
- const brokenConnectionError = getBrokenConnectionViolation(transactionViolations);
- const cardID = brokenConnectionError?.data?.cardID;
- const card = cardID ? cardList?.[cardID] : undefined;
-
- // Only suppress the status bar for a personal card the current user actually holds. A company card the
- // viewer doesn't own resolves to `undefined` here (it isn't in their cardList), and must still surface
- // the broken/re-auth status to admins and approvers.
- if (!!card && isPersonalCard(card) && brokenConnectionError) {
+ const brokenConnectionViolations = transactionViolations.filter(isBrokenConnectionViolation);
+
+ // Suppress the status only when every broken connection is on a personal card the current user holds.
+ // A company card missing from their cardList must still surface to admins and approvers.
+ if (shouldSuppressBrokenConnectionStatus(brokenConnectionViolations, cardList)) {
return undefined;
}
return {
diff --git a/src/hooks/useMoneyReportHeaderStatusBar.ts b/src/hooks/useMoneyReportHeaderStatusBar.ts
index 7c8842c93ad2..ebc2dd97e1fd 100644
--- a/src/hooks/useMoneyReportHeaderStatusBar.ts
+++ b/src/hooks/useMoneyReportHeaderStatusBar.ts
@@ -1,4 +1,3 @@
-import {isPersonalCard} from '@libs/CardUtils';
import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID';
import {getAllNonDeletedTransactions} from '@libs/MoneyRequestReportUtils';
import {getFilteredReportActionsForReportView, getOneTransactionThreadReportID, getOriginalMessage, isMoneyRequestAction} from '@libs/ReportActionsUtils';
@@ -6,12 +5,13 @@ import {isMarkAsResolvedAction} from '@libs/ReportPrimaryActionUtils';
import {hasOnlyHeldExpenses as hasOnlyHeldExpensesReportUtils, isSettled as isSettledReportUtils} from '@libs/ReportUtils';
import {
allHavePendingRTERViolation,
- getBrokenConnectionViolation,
hasDuplicateTransactions,
+ isBrokenConnectionViolation,
hasReceipt,
isPayAtEndExpense as isPayAtEndExpenseTransactionUtils,
isPending,
isScanning,
+ shouldSuppressBrokenConnectionStatus,
shouldShowBrokenConnectionViolationForMultipleTransactions,
} from '@libs/TransactionUtils';
@@ -122,14 +122,13 @@ function useMoneyReportHeaderStatusBar(reportID: string | undefined, chatReportI
if (hasDuplicates) {
return CONST.REPORT.STATUS_BAR_TYPE.DUPLICATES;
}
- if (!!transaction?.transactionID && !!transactionViolations.length && shouldShowBrokenConnectionViolation) {
- const brokenConnectionError = getBrokenConnectionViolation(transactionViolations);
- const cardID = brokenConnectionError?.data?.cardID;
- const card = cardID ? cardList?.[cardID] : undefined;
-
- // Only suppress the status bar for a personal card the current user actually holds. A company card the
- // viewer doesn't own resolves to `undefined` here, and must still surface the broken/re-auth status.
- if (!!card && isPersonalCard(card) && brokenConnectionError) {
+ if (shouldShowBrokenConnectionViolation) {
+ const brokenConnectionViolations = transactionViolations.length
+ ? transactionViolations.filter(isBrokenConnectionViolation)
+ : (visibleTransactions?.flatMap((t) => violations?.[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${t.transactionID}`] ?? []).filter(isBrokenConnectionViolation) ?? []);
+
+ // A report must retain a status if any violation needs an actionable or retry-later message.
+ if (shouldSuppressBrokenConnectionStatus(brokenConnectionViolations, cardList)) {
return undefined;
}
return CONST.REPORT.STATUS_BAR_TYPE.BROKEN_CONNECTION;
diff --git a/src/languages/de.ts b/src/languages/de.ts
index 732ce2fc8f7d..6fcc2682c5ef 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -10136,40 +10136,46 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
isMarkAsCash?: boolean,
) => {
if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
- return 'Beleg kann wegen unterbrochener Bankverbindung nicht automatisch zugeordnet werden.';
+ return 'Beleg kann aufgrund einer unterbrochenen Bankverbindung nicht automatisch zugeordnet werden.';
+ }
+ if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_531) {
+ return 'Beleg kann aufgrund eines vorübergehenden Bankproblems nicht automatisch zugeordnet werden. Bitte versuchen Sie es später noch einmal.';
}
if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_REAUTH) {
if (isPersonalCard) {
if (!connectionLink) {
- return 'Beleg kann nicht automatisch zugeordnet werden, da deine Bankverbindung erneut authentifiziert werden muss.';
+ return 'Beleg kann nicht automatisch zugeordnet werden, da Ihre Bankverbindung erneut authentifiziert werden muss.';
}
return isMarkAsCash
- ? `Beleg kann nicht automatisch zugeordnet werden, da deine Bankverbindung erneut authentifiziert werden muss. Markiere ihn als Barzahlung, um ihn zu ignorieren, oder verbinde dich erneut, um den Beleg zuzuordnen.`
- : `Beleg kann nicht automatisch zugeordnet werden, da deine Bankverbindung erneut authentifiziert werden muss. Erneut verbinden, um den Beleg zuzuordnen.`;
+ ? `Quittung kann nicht automatisch zugeordnet werden, da Ihre Bankverbindung erneut authentifiziert werden muss. Markieren Sie sie als Barzahlung, um dies zu ignorieren, oder verbinden Sie die Bank erneut, um die Quittung zuzuordnen.`
+ : `Beleg kann nicht automatisch zugeordnet werden, da Ihre Bankverbindung erneut authentifiziert werden muss. Erneut verbinden, um den Beleg zuzuordnen.`;
}
return isAdmin
? `Bankverbindung muss erneut authentifiziert werden. Erneut verbinden, um Beleg zuzuordnen`
- : 'Bankverbindung muss erneut authentifiziert werden. Bitte eine:n Admin bitten, die Verbindung wiederherzustellen, um den Beleg abzugleichen.';
+ : 'Die Bankverbindung muss erneut authentifiziert werden. Bitten Sie eine Adminperson, die Verbindung wiederherzustellen, um den Beleg abzugleichen.';
}
if (isPersonalCard && (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION || brokenBankConnection)) {
if (!connectionLink) {
- return 'Beleg kann wegen unterbrochener Bankverbindung nicht automatisch zugeordnet werden.';
+ return 'Beleg kann aufgrund einer unterbrochenen Bankverbindung nicht automatisch zugeordnet werden.';
}
return isMarkAsCash
- ? `Beleg kann wegen einer unterbrochenen Kartenverbindung nicht automatisch zugeordnet werden. Markiere ihn als Barzahlung, um ihn zu ignorieren, oder repariere die Karte, um den Beleg zuzuordnen.`
- : `Quittung kann aufgrund einer unterbrochenen Kartenverbindung nicht automatisch zugeordnet werden. Karte reparieren, um die Quittung zuzuordnen.`;
+ ? `Beleg kann wegen unterbrochener Kartenverbindung nicht automatisch zugeordnet werden. Markieren Sie ihn als Barzahlung, um ihn zu ignorieren, oder reparieren Sie die Karte, um den Beleg zuzuordnen.`
+ : `Beleg kann aufgrund einer unterbrochenen Kartenverbindung nicht automatisch zugeordnet werden. Karte reparieren, um den Beleg zuzuordnen.`;
}
if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
return isAdmin
? `Bankverbindung unterbrochen. Erneut verbinden, um Beleg zuzuordnen`
- : 'Bankverbindung unterbrochen. Bitte eine:n Admin bitten, die Verbindung wiederherzustellen, um den Beleg abzugleichen.';
+ : 'Bankverbindung unterbrochen. Bitten Sie eine Adminperson, die Verbindung wiederherzustellen, um den Beleg abzugleichen.';
}
if (!isTransactionOlderThan7Days) {
- return isAdmin ? `Bitte ${member} darum, es als Barzahlung zu markieren, oder warte 7 Tage und versuche es dann erneut` : 'Wartet auf Abgleich mit Kartentransaktion.';
+ return isAdmin
+ ? `Bitten Sie ${member}, dies als Barzahlung zu markieren, oder warten Sie 7 Tage und versuchen Sie es erneut`
+ : 'Warten auf Zusammenführung mit Kartentransaktion.';
}
return '';
},
brokenConnection530Error: 'Beleg ausstehend wegen unterbrochener Bankverbindung',
+ brokenConnection531Error: 'Beleg kann aufgrund eines vorübergehenden Bankproblems nicht automatisch zugeordnet werden. Bitte versuchen Sie es später noch einmal.',
adminBrokenConnectionError: ({workspaceCompanyCardRoute}: {workspaceCompanyCardRoute: string}) =>
`Beleg ausstehend wegen unterbrochener Bankverbindung. Bitte in Firmenkarten beheben.`,
memberBrokenConnectionError: 'Beleg ausstehend aufgrund einer unterbrochenen Bankverbindung. Bitte wende dich an eine Workspace-Admin, um das Problem zu beheben.',
diff --git a/src/languages/el.ts b/src/languages/el.ts
index 620b2e1a0094..d2eb035cd67c 100644
--- a/src/languages/el.ts
+++ b/src/languages/el.ts
@@ -10349,33 +10349,36 @@ ${reportName}`,
isMarkAsCash?: boolean,
) => {
if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
- return 'Δεν είναι δυνατή η αυτόματη αντιστοίχιση της απόδειξης λόγω σπασμένης σύνδεσης με την τράπεζα.';
+ return 'Δεν είναι δυνατή η αυτόματη αντιστοίχιση της απόδειξης λόγω σφάλματος σύνδεσης με την τράπεζα.';
+ }
+ if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_531) {
+ return 'Δεν είναι δυνατή η αυτόματη αντιστοίχιση της απόδειξης λόγω προσωρινού προβλήματος της τράπεζας. Παρακαλούμε δοκιμάστε ξανά αργότερα.';
}
if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_REAUTH) {
if (isPersonalCard) {
if (!connectionLink) {
- return 'Δεν είναι δυνατή η αυτόματη αντιστοίχιση της απόδειξης, επειδή η σύνδεση με την τράπεζα χρειάζεται εκ νέου ταυτοποίηση.';
+ return 'Δεν είναι δυνατή η αυτόματη αντιστοίχιση της απόδειξης, επειδή η σύνδεση με την τράπεζά σας χρειάζεται εκ νέου έλεγχο ταυτότητας.';
}
return isMarkAsCash
- ? `Δεν είναι δυνατή η αυτόματη αντιστοίχιση της απόδειξης, επειδή η σύνδεση με την τράπεζα χρειάζεται εκ νέου ταυτοποίηση. Σημειώστε την ως μετρητά για να την αγνοήσετε ή επανασυνδεθείτε για να αντιστοιχίσετε την απόδειξη.`
- : `Δεν είναι δυνατή η αυτόματη αντιστοίχιση της απόδειξης, επειδή η σύνδεση με την τράπεζα χρειάζεται εκ νέου ταυτοποίηση. Επανασυνδεθείτε για να αντιστοιχίσετε την απόδειξη.`;
+ ? `Δεν είναι δυνατή η αυτόματη αντιστοίχιση της απόδειξης επειδή η σύνδεση με την τράπεζά σας χρειάζεται επαναπιστοποίηση. Σημειώστε ως μετρητά για να αγνοήσετε ή επανασυνδεθείτε για να αντιστοιχίσετε την απόδειξη.`
+ : `Δεν είναι δυνατή η αυτόματη αντιστοίχιση της απόδειξης, επειδή η σύνδεσή σας με την τράπεζα χρειάζεται νέα εξακρίβωση. Επανασυνδεθείτε για να γίνει η αντιστοίχιση της απόδειξης.`;
}
return isAdmin
- ? `Η σύνδεση με την τράπεζα χρειάζεται εκ νέου ταυτοποίηση. Επανασυνδέστε για να αντιστοιχίσετε την απόδειξη`
- : 'Η σύνδεση με την τράπεζα χρειάζεται εκ νέου ταυτοποίηση. Ζητήστε από ένα διαχειριστή να την επανασυνδέσει για να γίνει αντιστοίχιση της απόδειξης.';
+ ? `Η σύνδεση με την τράπεζα χρειάζεται νέα πιστοποίηση. Επανασυνδεθείτε για να αντιστοιχίσετε την απόδειξη`
+ : 'Η σύνδεση με την τράπεζα χρειάζεται επανεξουσιοδότηση. Ζητήστε από έναν διαχειριστή να την επανασυνδέσει για να ταιριάζει με την απόδειξη.';
}
if (isPersonalCard && (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION || brokenBankConnection)) {
if (!connectionLink) {
- return 'Δεν είναι δυνατή η αυτόματη αντιστοίχιση της απόδειξης λόγω σπασμένης σύνδεσης με την τράπεζα.';
+ return 'Δεν είναι δυνατή η αυτόματη αντιστοίχιση της απόδειξης λόγω σφάλματος σύνδεσης με την τράπεζα.';
}
return isMarkAsCash
- ? `Δεν είναι δυνατή η αυτόματη αντιστοίχιση της απόδειξης λόγω χαλασμένης σύνδεσης κάρτας. Σημειώστε την ως μετρητά για να την αγνοήσετε ή διορθώστε την κάρτα για να αντιστοιχίσετε την απόδειξη.`
- : `Δεν είναι δυνατή η αυτόματη αντιστοίχιση της απόδειξης λόγω χαλασμένης σύνδεσης της κάρτας. Διορθώστε την κάρτα για να αντιστοιχίσετε την απόδειξη.`;
+ ? `Δεν είναι δυνατή η αυτόματη αντιστοίχιση της απόδειξης λόγω σπασμένης σύνδεσης κάρτας. Επισημάνετε ως μετρητά για να την αγνοήσετε ή διορθώστε την κάρτα για να αντιστοιχίσετε την απόδειξη.`
+ : `Δεν είναι δυνατή η αυτόματη αντιστοίχιση της απόδειξης λόγω προβληματικής σύνδεσης της κάρτας. Επιδιορθώστε την κάρτα για να αντιστοιχίσετε την απόδειξη.`;
}
if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
return isAdmin
? `Η σύνδεση με την τράπεζα διακόπηκε. Επανασυνδέστε για να αντιστοιχίσετε την απόδειξη`
- : 'Η σύνδεση με την τράπεζα διακόπηκε. Ζητήστε από ένα διαχειριστή να την επανασυνδέσει για να γίνει αντιστοίχιση της απόδειξης.';
+ : 'Η σύνδεση με την τράπεζα έχει διακοπεί. Ζητήστε από έναν διαχειριστή να την επανασυνδέσει για να γίνει αντιστοίχιση με την απόδειξη.';
}
if (!isTransactionOlderThan7Days) {
return isAdmin ? `Ζητήστε από τον/την ${member} να το σημειώσει ως μετρητά ή περιμένετε 7 ημέρες και δοκιμάστε ξανά` : 'Αναμονή για συγχώνευση με συναλλαγή κάρτας.';
@@ -10383,6 +10386,7 @@ ${reportName}`,
return '';
},
brokenConnection530Error: 'Η απόδειξη εκκρεμεί λόγω αποσυνδεδεμένου τραπεζικού λογαριασμού',
+ brokenConnection531Error: 'Δεν είναι δυνατή η αυτόματη αντιστοίχιση της απόδειξης λόγω προσωρινού προβλήματος της τράπεζας. Παρακαλούμε δοκιμάστε ξανά αργότερα.',
adminBrokenConnectionError: ({workspaceCompanyCardRoute}: {workspaceCompanyCardRoute: string}) =>
`Η απόδειξη εκκρεμεί λόγω κατεστραμμένης σύνδεσης τράπεζας. Παρακαλώ επιλύστε το στις εταιρικές κάρτες.`,
memberBrokenConnectionError: 'Η απόδειξη εκκρεμεί λόγω προβλήματος στη σύνδεση με την τράπεζα. Παρακαλείστε να ζητήσετε από έναν διαχειριστή χώρου εργασίας να το επιλύσει.',
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 9829bfebbc62..5489c6b24db0 100644
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -10280,6 +10280,9 @@ const translations = {
if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
return "Can't auto-match receipt due to broken bank connection.";
}
+ if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_531) {
+ return "Can't auto-match receipt due to a temporary bank issue. Please try again later.";
+ }
if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_REAUTH) {
if (isPersonalCard) {
if (!connectionLink) {
@@ -10313,6 +10316,7 @@ const translations = {
return '';
},
brokenConnection530Error: 'Receipt pending due to broken bank connection',
+ brokenConnection531Error: "Can't auto-match receipt due to a temporary bank issue. Please try again later.",
adminBrokenConnectionError: ({workspaceCompanyCardRoute}: {workspaceCompanyCardRoute: string}) =>
`Receipt pending due to broken bank connection. Please resolve in Company cards.`,
memberBrokenConnectionError: 'Receipt pending due to broken bank connection. Please ask a workspace admin to resolve.',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index e8f93a9ef38b..97988a2022ae 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -12,6 +12,8 @@
import CONST from '@src/CONST';
import type {OriginalMessageReportPreview, OriginalMessageSettlementAccountLocked, PersonalRulesModifiedFields, PolicyRulesModifiedFields} from '@src/types/onyx/OriginalMessage';
+import type {ValueOf} from 'type-fest';
+
import {CONST as COMMON_CONST, Str} from 'expensify-common';
import type en from './en';
@@ -10338,44 +10340,56 @@ ${reportName}`,
},
customRules: (message) => message,
reviewRequired: 'Revisión requerida',
- rter: (brokenBankConnection, isAdmin, isTransactionOlderThan7Days, member, rterType, companyCardPageURL, connectionLink, isPersonalCard, isMarkAsCash) => {
+ rter: (
+ brokenBankConnection: boolean,
+ isAdmin: boolean,
+ isTransactionOlderThan7Days: boolean,
+ member?: string,
+ rterType?: ValueOf,
+ companyCardPageURL?: string,
+ connectionLink?: string,
+ isPersonalCard?: boolean,
+ isMarkAsCash?: boolean,
+ ) => {
if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
- return 'No se puede emparejar automáticamente el recibo debido a una conexión bancaria interrumpida.';
+ return 'No se puede vincular automáticamente el recibo debido a una conexión bancaria interrumpida.';
+ }
+ if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_531) {
+ return 'No se puede conciliar automáticamente el recibo debido a un problema bancario temporal. Por favor, inténtalo de nuevo más tarde.';
}
if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_REAUTH) {
if (isPersonalCard) {
if (!connectionLink) {
- return 'No se puede emparejar automáticamente el recibo porque tu conexión bancaria necesita volver a autenticarse.';
+ return 'No se puede hacer la conciliación automática del recibo porque tu conexión bancaria necesita volver a autenticarse.';
}
return isMarkAsCash
- ? `No se puede emparejar automáticamente el recibo porque tu conexión bancaria necesita volver a autenticarse. Márcalo como efectivo para ignorarlo o vuelve a conectarte para asociar el recibo.`
- : `No se puede emparejar automáticamente el recibo porque tu conexión bancaria necesita volver a autenticarse. Vuelve a conectarte para asociar el recibo.`;
+ ? `No se puede conciliar automáticamente el recibo porque tu conexión bancaria necesita volver a autenticarse. Márcalo como en efectivo para ignorarlo o vuelve a conectar para conciliar el recibo.`
+ : `No se puede conciliar automáticamente el recibo porque tu conexión bancaria necesita volver a autenticarse. Vuelve a conectar para conciliar el recibo.`;
}
return isAdmin
- ? `La conexión bancaria necesita volver a autenticarse. Vuelve a conectarte para emparejar el recibo`
- : 'La conexión bancaria necesita volver a autenticarse. Pide a un administrador que la vuelva a conectar para emparejar el recibo.';
+ ? `La conexión bancaria necesita volver a autenticar. Vuelve a conectar para hacer coincidir el recibo`
+ : 'La conexión bancaria necesita volver a autenticarse. Pide a una persona administradora que la vuelva a conectar para que coincida con el recibo.';
}
if (isPersonalCard && (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION || brokenBankConnection)) {
if (!connectionLink) {
- return 'No se puede emparejar automáticamente el recibo debido a una conexión bancaria interrumpida.';
+ return 'No se puede vincular automáticamente el recibo debido a una conexión bancaria interrumpida.';
}
return isMarkAsCash
- ? `No se puede vincular automáticamente el recibo debido a un problema de conexión de la tarjeta. Márcalo como efectivo para ignorarlo o soluciona la conexión de la tarjeta para asociar el recibo.`
- : `No se puede vincular automáticamente el recibo debido a un problema de conexión de la tarjeta. Soluciona la conexión de la tarjeta para asociar el recibo.`;
+ ? `No se puede conciliar automáticamente el recibo debido a una conexión de tarjeta rota. Márcalo como efectivo para ignorarlo o repara la tarjeta para conciliar el recibo.`
+ : `No se puede asociar automáticamente el recibo debido a una conexión de tarjeta rota. Repara la tarjeta para asociar el recibo.`;
}
if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
return isAdmin
- ? `Conexión bancaria interrumpida. Vuelve a conectarte para emparejar el recibo`
- : 'Conexión bancaria interrumpida. Pide a un administrador que la vuelva a conectar para emparejar el recibo.';
+ ? `Conexión bancaria interrumpida. Vuelve a conectar para hacer coincidir el recibo`
+ : 'Conexión bancaria interrumpida. Pide a un administrador que la vuelva a conectar para que coincida con el recibo.';
}
if (!isTransactionOlderThan7Days) {
- return isAdmin
- ? `Pide a ${member} que marque la transacción como efectivo o espera 7 días e inténtalo de nuevo`
- : 'Esperando a adjuntar automáticamente la transacción de tarjeta de crédito';
+ return isAdmin ? `Pídele a ${member} que lo marque como efectivo o espera 7 días e inténtalo de nuevo` : 'En espera de combinarse con la transacción de tarjeta.';
}
return '';
},
brokenConnection530Error: 'Recibo pendiente debido a una conexión bancaria rota',
+ brokenConnection531Error: 'No se puede conciliar automáticamente el recibo debido a un problema bancario temporal. Por favor, inténtalo de nuevo más tarde.',
adminBrokenConnectionError: ({workspaceCompanyCardRoute}) =>
`Recibo pendiente debido a una conexión bancaria rota. Por favor, resuélvelo en Tarjetas de empresa.`,
memberBrokenConnectionError: 'Recibo pendiente debido a una conexión bancaria rota. Por favor, pide a un administrador del espacio de trabajo que lo resuelva.',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index b222092dee3d..316057f17d11 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -10167,40 +10167,44 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
isMarkAsCash?: boolean,
) => {
if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
- return 'Impossible d’apparier automatiquement le reçu en raison d’une connexion bancaire rompue.';
+ return 'Impossible d’associer automatiquement le reçu en raison d’une connexion bancaire rompue.';
+ }
+ if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_531) {
+ return 'Impossible d’associer automatiquement le reçu en raison d’un problème bancaire temporaire. Veuillez réessayer ultérieurement.';
}
if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_REAUTH) {
if (isPersonalCard) {
if (!connectionLink) {
- return 'Impossible d’apparier automatiquement le reçu car votre connexion bancaire doit être ré-authentifiée.';
+ return 'Impossible d’associer automatiquement le reçu, car votre connexion bancaire doit être réauthentifiée.';
}
return isMarkAsCash
- ? `Impossible d’apparier automatiquement le reçu car votre connexion bancaire doit être ré-authentifiée. Marquez-le comme paiement en espèces pour l’ignorer, ou reconnectez-vous pour associer le reçu.`
- : `Impossible d’apparier automatiquement le reçu car votre connexion bancaire doit être ré-authentifiée. Reconnectez-vous pour associer le reçu.`;
+ ? `Impossible de faire correspondre automatiquement le reçu, car votre connexion bancaire nécessite une nouvelle authentification. Marquez-le comme espèces pour ignorer, ou reconnectez-vous pour faire correspondre le reçu.`
+ : `Impossible d’associer automatiquement le reçu, car la connexion à votre banque nécessite une nouvelle authentification. Reconnectez-vous pour associer le reçu.`;
}
return isAdmin
- ? `La connexion bancaire doit être ré-authentifiée. Reconnectez-vous pour faire correspondre le reçu`
- : 'La connexion bancaire doit être ré-authentifiée. Demandez à un administrateur de la reconnecter pour faire correspondre le reçu.';
+ ? `La connexion bancaire nécessite une nouvelle authentification. Reconnectez-vous pour faire correspondre le reçu`
+ : 'La connexion bancaire doit être réauthentifiée. Demandez à un administrateur de la reconnecter pour faire correspondre le reçu.';
}
if (isPersonalCard && (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION || brokenBankConnection)) {
if (!connectionLink) {
- return 'Impossible d’apparier automatiquement le reçu en raison d’une connexion bancaire rompue.';
+ return 'Impossible d’associer automatiquement le reçu en raison d’une connexion bancaire rompue.';
}
return isMarkAsCash
- ? `Impossible d'associer automatiquement le reçu en raison d'une connexion de carte défectueuse. Marquez-le comme paiement en espèces pour l'ignorer, ou corrigez la carte pour associer le reçu.`
- : `Impossible d'associer automatiquement le reçu en raison d'une connexion de carte rompue. Réparez la carte pour faire correspondre le reçu.`;
+ ? `Impossible d’associer automatiquement le reçu en raison d’une connexion carte défectueuse. Marquez-le comme espèce pour ignorer, ou réparez la carte pour faire correspondre le reçu.`
+ : `Impossible d’associer automatiquement le reçu en raison d’une connexion carte défectueuse. Réparez la carte pour associer le reçu.`;
}
if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
return isAdmin
- ? `Connexion bancaire rompue. Reconnectez-vous pour faire correspondre le reçu`
- : 'Connexion bancaire interrompue. Demandez à un administrateur de la reconnecter pour faire correspondre le reçu.';
+ ? `Connexion bancaire interrompue. Reconnecter pour faire correspondre le reçu`
+ : 'Connexion bancaire rompue. Demandez à un administrateur de la reconnecter pour faire correspondre le reçu.';
}
if (!isTransactionOlderThan7Days) {
- return isAdmin ? `Demandez à ${member} de marquer comme paiement en espèces ou attendez 7 jours et réessayez` : 'En attente de fusion avec la transaction par carte.';
+ return isAdmin ? `Demandez à ${member} de le marquer comme espèces ou attendez 7 jours et réessayez` : 'En attente de fusion avec la transaction par carte.';
}
return '';
},
brokenConnection530Error: 'Reçu en attente en raison d’une connexion bancaire rompue',
+ brokenConnection531Error: 'Impossible d’associer automatiquement le reçu en raison d’un problème bancaire temporaire. Veuillez réessayer ultérieurement.',
adminBrokenConnectionError: ({workspaceCompanyCardRoute}: {workspaceCompanyCardRoute: string}) =>
`Reçu en attente en raison d’une connexion bancaire rompue. Veuillez résoudre le problème dans les Cartes d’entreprise.`,
memberBrokenConnectionError: 'Reçu en attente en raison d’une connexion bancaire rompue. Veuillez demander à un administrateur de l’espace de travail de résoudre le problème.',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 973fe6790d21..74f8e5feaf95 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -10101,28 +10101,31 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
isMarkAsCash?: boolean,
) => {
if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
- return 'Impossibile abbinare automaticamente la ricevuta a causa di un problema di connessione bancaria.';
+ return 'Impossibile abbinare automaticamente la ricevuta a causa di un problema di connessione con la banca.';
+ }
+ if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_531) {
+ return 'Impossibile associare automaticamente la ricevuta a causa di un problema temporaneo della banca. Riprova più tardi.';
}
if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_REAUTH) {
if (isPersonalCard) {
if (!connectionLink) {
- return 'Impossibile abbinare automaticamente la ricevuta perché la connessione bancaria deve essere ri-autenticata.';
+ return 'Impossibile abbinare automaticamente la ricevuta perché la connessione bancaria richiede una nuova autenticazione.';
}
return isMarkAsCash
- ? `Impossibile abbinare automaticamente la ricevuta perché la connessione bancaria deve essere ri-autenticata. Contrassegna come contanti per ignorare oppure riconnettiti per abbinare la ricevuta.`
- : `Impossibile abbinare automaticamente la ricevuta perché la connessione bancaria deve essere ri-autenticata. Riconnettiti per abbinare la ricevuta.`;
+ ? `Impossibile abbinare automaticamente la ricevuta perché il collegamento alla banca richiede una nuova autenticazione. Contrassegna come contante per ignorare oppure riconnetti per abbinare la ricevuta.`
+ : `Impossibile abbinare automaticamente la ricevuta perché la connessione bancaria richiede una nuova autenticazione. Riconnetti per abbinare la ricevuta.`;
}
return isAdmin
- ? `La connessione bancaria deve essere ri-autenticata. Riconnetti per abbinare la ricevuta`
- : 'La connessione bancaria deve essere ri-autenticata. Chiedi a un amministratore di riconnetterla per abbinare la ricevuta.';
+ ? `La connessione bancaria richiede una nuova autenticazione. Riconnetti per abbinare la ricevuta`
+ : 'La connessione bancaria richiede una nuova autenticazione. Chiedi a un amministratore di riconnetterla per abbinarla alla ricevuta.';
}
if (isPersonalCard && (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION || brokenBankConnection)) {
if (!connectionLink) {
- return 'Impossibile abbinare automaticamente la ricevuta a causa di un problema di connessione bancaria.';
+ return 'Impossibile abbinare automaticamente la ricevuta a causa di un problema di connessione con la banca.';
}
return isMarkAsCash
- ? `Impossibile abbinare automaticamente la ricevuta a causa di un problema di connessione della carta. Contrassegna come contanti per ignorare oppure sistema la carta per abbinare la ricevuta.`
- : `Impossibile abbinare automaticamente la ricevuta a causa di un problema di connessione con la carta. Correggi la carta per abbinarla alla ricevuta.`;
+ ? `Impossibile abbinare automaticamente la ricevuta a causa di un problema di connessione della carta. Contrassegna come contanti per ignorare oppure sistema la carta per abbinarla alla ricevuta.`
+ : `Impossibile abbinare automaticamente la ricevuta a causa di un problema di connessione della carta. Sistema la carta per abbinarla alla ricevuta.`;
}
if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
return isAdmin
@@ -10130,11 +10133,12 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
: 'Connessione bancaria interrotta. Chiedi a un amministratore di riconnetterla per abbinare la ricevuta.';
}
if (!isTransactionOlderThan7Days) {
- return isAdmin ? `Chiedi a ${member} di contrassegnarla come contante oppure attendi 7 giorni e riprova` : 'In attesa di abbinamento con la transazione della carta.';
+ return isAdmin ? `Chiedi a ${member} di contrassegnarla come contante oppure aspetta 7 giorni e riprova` : 'In attesa di unire con la transazione della carta.';
}
return '';
},
brokenConnection530Error: 'Ricevuta in sospeso a causa di connessione bancaria interrotta',
+ brokenConnection531Error: 'Impossibile associare automaticamente la ricevuta a causa di un problema temporaneo della banca. Riprova più tardi.',
adminBrokenConnectionError: ({workspaceCompanyCardRoute}: {workspaceCompanyCardRoute: string}) =>
`Ricevuta in sospeso a causa di un collegamento bancario interrotto. Risolvi il problema in Carte aziendali.`,
memberBrokenConnectionError: 'Ricevuta in sospeso a causa di un collegamento bancario interrotto. Chiedi a un amministratore dello spazio di lavoro di risolvere il problema.',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index ed0fae073dc2..cea918fcf27f 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -9958,38 +9958,42 @@ ${reportName}`,
if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
return '銀行連携の不具合により、領収書を自動照合できません。';
}
+ if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_531) {
+ return '一時的な銀行側の問題により、レシートを自動照合できません。後でもう一度お試しください。';
+ }
if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_REAUTH) {
if (isPersonalCard) {
if (!connectionLink) {
return '銀行連携の再認証が必要なため、領収書を自動照合できません。';
}
return isMarkAsCash
- ? `銀行連携の再認証が必要なため、領収書を自動照合できません。無視するには現金としてマークするか、再接続して領収書と照合してください。`
+ ? `銀行連携の再認証が必要なため、領収書を自動照合できません。無視するには現金としてマークするか、再接続して領収書を照合してください。`
: `銀行連携の再認証が必要なため、領収書を自動照合できません。領収書を照合するには、再接続してください。`;
}
return isAdmin
- ? `銀行連携の再認証が必要です。レシートと照合するために再接続`
- : '銀行連携の再認証が必要です。管理者に依頼して再接続し、領収書と照合してください。';
+ ? `銀行連携の再認証が必要です。領収書と照合するために再接続する`
+ : '銀行連携の再認証が必要です。管理者に依頼して再接続し、レシートと照合してください。';
}
if (isPersonalCard && (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION || brokenBankConnection)) {
if (!connectionLink) {
return '銀行連携の不具合により、領収書を自動照合できません。';
}
return isMarkAsCash
- ? `カード連携の不具合により領収書を自動照合できません。無視するには現金としてマークするか、カードを修正して領収書と照合してください。`
- : `カード連携が壊れているため、領収書を自動照合できません。領収書を照合するには、カードの問題を解決してください。`;
+ ? `カード連携の不具合により、レシートを自動照合できません。無視する場合は現金としてマークするか、レシートを照合するにはカード連携を修正してください。`
+ : `カード連携に問題があるため、領収書を自動照合できません。領収書を照合するには、カードの問題を修正してください。`;
}
if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
return isAdmin
- ? `銀行連携が切断されました。レシートと照合するために再接続`
+ ? `銀行との接続が切れています。再接続して領収書を照合する`
: '銀行連携が切断されています。管理者に依頼して再接続し、領収書と照合してください。';
}
if (!isTransactionOlderThan7Days) {
- return isAdmin ? `${member} に現金としてマークするよう依頼するか、7日待ってから再試行してください` : 'カード取引との照合待ちです。';
+ return isAdmin ? `${member} に現金としてマークするよう依頼するか、7日待ってから再試行してください` : 'カード取引との統合待ちです。';
}
return '';
},
brokenConnection530Error: '銀行連携の不具合により領収書が保留されています',
+ brokenConnection531Error: '一時的な銀行側の問題により、レシートを自動照合できません。後でもう一度お試しください。',
adminBrokenConnectionError: ({workspaceCompanyCardRoute}: {workspaceCompanyCardRoute: string}) =>
`銀行接続の不具合により領収書が保留されています。会社カードで解決してください。`,
memberBrokenConnectionError: '銀行連携の不具合により領収書が保留されています。ワークスペース管理者に対応を依頼してください。',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index ca2b4bf455e4..b14357301c3c 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -10056,47 +10056,51 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
isAdmin: boolean,
isTransactionOlderThan7Days: boolean,
member?: string,
- rterType?: string,
+ rterType?: ValueOf,
companyCardPageURL?: string,
connectionLink?: string,
isPersonalCard?: boolean,
isMarkAsCash?: boolean,
) => {
if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
- return 'Bon kan automatisch aan bon koppelen vanwege verbroken bankverbinding.';
+ return 'Kan bon niet automatisch koppelen door een verbroken bankverbinding.';
+ }
+ if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_531) {
+ return 'Kan bon niet automatisch koppelen vanwege een tijdelijk bankprobleem. Probeer het later opnieuw.';
}
if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_REAUTH) {
if (isPersonalCard) {
if (!connectionLink) {
- return 'Kan bon niet automatisch koppelen omdat je bankverbinding opnieuw geverifieerd moet worden.';
+ return 'Kan de bon niet automatisch koppelen omdat je bankverbinding opnieuw moet worden geverifieerd.';
}
return isMarkAsCash
- ? `Kan bon niet automatisch koppelen omdat je bankverbinding opnieuw geverifieerd moet worden. Markeer als contant om te negeren, of verbind opnieuw om de bon te koppelen.`
- : `Kan bon niet automatisch koppelen omdat je bankverbinding opnieuw geverifieerd moet worden. Verbind opnieuw om de bon te koppelen.`;
+ ? `Kan bon niet automatisch koppelen omdat je bankverbinding opnieuw moet worden geverifieerd. Markeer als contant om te negeren, of maak opnieuw verbinding om de bon te koppelen.`
+ : `Kan de bon niet automatisch koppelen omdat je bankverbinding opnieuw moet worden geverifieerd. Verbind opnieuw om de bon te koppelen.`;
}
return isAdmin
- ? `Bankkoppeling moet opnieuw worden geverifieerd. Opnieuw verbinden om bon te koppelen`
- : 'Bankkoppeling moet opnieuw worden geverifieerd. Vraag een beheerder om de verbinding opnieuw te maken om de bon te laten overeenkomen.';
+ ? `Bankverbinding moet opnieuw worden geverifieerd. Opnieuw verbinden om bon te koppelen`
+ : 'Bankkoppeling moet opnieuw worden geverifieerd. Vraag een beheerder om opnieuw te verbinden zodat het overeenkomt met de bon.';
}
if (isPersonalCard && (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION || brokenBankConnection)) {
if (!connectionLink) {
- return 'Bon kan automatisch aan bon koppelen vanwege verbroken bankverbinding.';
+ return 'Kan bon niet automatisch koppelen door een verbroken bankverbinding.';
}
return isMarkAsCash
- ? `Kan bon niet automatisch koppelen vanwege een verbroken kaartverbinding. Markeer als contant om te negeren, of repareer de kaart om de bon te koppelen.`
- : `Kan bon automatisch koppelen aan bon vanwege verbroken kaartverbinding. Herstel de kaart om de bon te koppelen.`;
+ ? `Kan bon niet automatisch koppelen vanwege een verbroken kaartverbinding. Markeer als contant om te negeren, of herstel de kaart om de bon te koppelen.`
+ : `Kan bon niet automatisch koppelen vanwege een verbroken kaartverbinding. Herstel de kaart om de bon te koppelen.`;
}
if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
return isAdmin
- ? `Bankkoppeling verbroken. Opnieuw verbinden om bon te koppelen`
- : 'Bankkoppeling verbroken. Vraag een beheerder om de verbinding opnieuw te maken om de bon te laten overeenkomen.';
+ ? `Bankverbinding verbroken. Opnieuw verbinden om bon te koppelen`
+ : 'Bankkoppeling verbroken. Vraag een admin om opnieuw te verbinden om de bon te koppelen.';
}
if (!isTransactionOlderThan7Days) {
- return isAdmin ? `Vraag ${member} om het als contant te markeren of wacht 7 dagen en probeer het opnieuw` : 'In afwachting van koppeling met kaarttransactie.';
+ return isAdmin ? `Vraag ${member} om deze als contant te markeren of wacht 7 dagen en probeer het opnieuw` : 'In afwachting van samenvoeging met kaarttransactie.';
}
return '';
},
brokenConnection530Error: 'Bonnetje in behandeling vanwege verbroken bankverbinding',
+ brokenConnection531Error: 'Kan bon niet automatisch koppelen vanwege een tijdelijk bankprobleem. Probeer het later opnieuw.',
adminBrokenConnectionError: ({workspaceCompanyCardRoute}: {workspaceCompanyCardRoute: string}) =>
`Bon in behandeling vanwege een verbroken bankverbinding. Los dit op in Bedrijfspassen.`,
memberBrokenConnectionError: 'Bon wordt vastgehouden vanwege een verbroken bankkoppeling. Vraag een werkruimtebeheerder om dit op te lossen.',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 2b117cb2fd9a..1283b4568e84 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -10078,7 +10078,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
isAdmin: boolean,
isTransactionOlderThan7Days: boolean,
member?: string,
- rterType?: string,
+ rterType?: ValueOf,
companyCardPageURL?: string,
connectionLink?: string,
isPersonalCard?: boolean,
@@ -10087,38 +10087,42 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
return 'Nie można automatycznie dopasować paragonu z powodu zerwanego połączenia z bankiem.';
}
+ if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_531) {
+ return 'Nie można automatycznie dopasować paragonu z powodu tymczasowego problemu z bankiem. Spróbuj ponownie później.';
+ }
if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_REAUTH) {
if (isPersonalCard) {
if (!connectionLink) {
return 'Nie można automatycznie dopasować paragonu, ponieważ połączenie z bankiem wymaga ponownego uwierzytelnienia.';
}
return isMarkAsCash
- ? `Nie można automatycznie dopasować paragonu, ponieważ połączenie z bankiem wymaga ponownego uwierzytelnienia. Oznacz jako gotówkę, aby zignorować, lub połącz ponownie, aby dopasować paragon.`
+ ? `Nie można automatycznie dopasować paragonu, bo Twoje połączenie z bankiem wymaga ponownego uwierzytelnienia. Oznacz jako gotówkę, żeby zignorować, albo połącz ponownie, żeby dopasować paragon.`
: `Nie można automatycznie dopasować paragonu, ponieważ połączenie z bankiem wymaga ponownego uwierzytelnienia. Połącz ponownie, aby dopasować paragon.`;
}
return isAdmin
- ? `Połączenie z bankiem wymaga ponownego uwierzytelnienia. Połącz ponownie, aby dopasować paragon`
- : 'Połączenie z bankiem wymaga ponownego uwierzytelnienia. Poproś administratora o ponowne połączenie, aby dopasować paragon.';
+ ? `Połączenie z bankiem wymaga ponownego uwierzytelnienia. Połącz ponownie, żeby dopasować paragon`
+ : 'Połączenie z bankiem wymaga ponownego uwierzytelnienia. Poproś administratora o ponowne połączenie, żeby dopasować paragon.';
}
if (isPersonalCard && (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION || brokenBankConnection)) {
if (!connectionLink) {
return 'Nie można automatycznie dopasować paragonu z powodu zerwanego połączenia z bankiem.';
}
return isMarkAsCash
- ? `Nie można automatycznie dopasować paragonu z powodu zerwanego połączenia z kartą. Oznacz jako gotówkę, aby zignorować, lub napraw kartę, aby dopasować paragon.`
- : `Nie można automatycznie dopasować paragonu z powodu przerwanego połączenia karty. Napraw kartę, aby dopasować paragon.`;
+ ? `Nie można automatycznie dopasować paragonu z powodu zerwanego połączenia z kartą. Oznacz wydatek jako gotówkę, aby go zignorować, albo napraw kartę, żeby dopasować paragon.`
+ : `Nie można automatycznie dopasować paragonu z powodu zerwanego połączenia z kartą. Napraw kartę, żeby dopasować paragon.`;
}
if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
return isAdmin
- ? `Połączenie z bankiem przerwane. Połącz ponownie, aby dopasować paragon`
- : 'Połączenie z bankiem zostało przerwane. Poproś administratora o ponowne połączenie, aby dopasować paragon.';
+ ? `Połączenie z bankiem zostało zerwane. Połącz ponownie, aby dopasować paragon`
+ : 'Połączenie z bankiem zostało zerwane. Poproś administratora o ponowne połączenie, aby dopasować paragon.';
}
if (!isTransactionOlderThan7Days) {
- return isAdmin ? `Poproś ${member}, aby oznaczył to jako gotówkę, albo poczekaj 7 dni i spróbuj ponownie` : 'Oczekiwanie na połączenie z transakcją kartową.';
+ return isAdmin ? `Poproś ${member}, żeby oznaczył to jako gotówkę albo poczekaj 7 dni i spróbuj ponownie` : 'Oczekuje na połączenie z transakcją z karty.';
}
return '';
},
brokenConnection530Error: 'Paragon oczekuje z powodu przerwanego połączenia z bankiem',
+ brokenConnection531Error: 'Nie można automatycznie dopasować paragonu z powodu tymczasowego problemu z bankiem. Spróbuj ponownie później.',
adminBrokenConnectionError: ({workspaceCompanyCardRoute}: {workspaceCompanyCardRoute: string}) =>
`Oczekuje na rachunek z powodu przerwanego połączenia z bankiem. Rozwiąż problem w sekcji Karty firmowe.`,
memberBrokenConnectionError: 'Paragon oczekuje z powodu zerwanego połączenia z bankiem. Poproś administratora przestrzeni roboczej o rozwiązanie problemu.',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index e6cc5e2d0149..368adf8abc2d 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -10057,47 +10057,51 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
isAdmin: boolean,
isTransactionOlderThan7Days: boolean,
member?: string,
- rterType?: string,
+ rterType?: ValueOf,
companyCardPageURL?: string,
connectionLink?: string,
isPersonalCard?: boolean,
isMarkAsCash?: boolean,
) => {
if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
- return 'Não é possível conciliar automaticamente o recibo devido a uma conexão bancária com erro.';
+ return 'Não foi possível associar o recibo automaticamente devido a uma conexão bancária com problema.';
+ }
+ if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_531) {
+ return 'Não foi possível associar automaticamente o recibo devido a um problema temporário no banco. Tente novamente mais tarde.';
}
if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_REAUTH) {
if (isPersonalCard) {
if (!connectionLink) {
- return 'Não é possível conciliar automaticamente o recibo porque sua conexão bancária precisa ser reautenticada.';
+ return 'Não foi possível associar o recibo automaticamente porque sua conexão bancária precisa ser reautenticada.';
}
return isMarkAsCash
- ? `Não é possível conciliar automaticamente o recibo porque sua conexão bancária precisa ser reautenticada. Marque como dinheiro para ignorar ou reconecte para corresponder o recibo.`
- : `Não é possível conciliar automaticamente o recibo porque sua conexão bancária precisa ser reautenticada. Reconecte para corresponder o recibo.`;
+ ? `Não é possível fazer a correspondência automática do recibo porque a conexão com seu banco precisa ser reautenticada. Marque como dinheiro para ignorar ou reconecte para corresponder o recibo.`
+ : `Não é possível fazer a correspondência automática do recibo porque a conexão com seu banco precisa ser reautenticada. Reconectar para corresponder o recibo.`;
}
return isAdmin
- ? `A conexão bancária precisa ser reautenticada. Reconectar para corresponder ao recibo`
- : 'A conexão bancária precisa ser reautenticada. Peça para um administrador reconectar para corresponder ao recibo.';
+ ? `A conexão bancária precisa ser autenticada novamente. Reconectar para corresponder ao recibo`
+ : 'A conexão com o banco precisa de nova autenticação. Peça para um administrador reconectar para corresponder ao recibo.';
}
if (isPersonalCard && (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION || brokenBankConnection)) {
if (!connectionLink) {
- return 'Não é possível conciliar automaticamente o recibo devido a uma conexão bancária com erro.';
+ return 'Não foi possível associar o recibo automaticamente devido a uma conexão bancária com problema.';
}
return isMarkAsCash
- ? `Não é possível corresponder automaticamente o recibo devido a uma conexão de cartão com problema. Marque como dinheiro para ignorar ou corrija o cartão para corresponder o recibo.`
- : `Não é possível corresponder automaticamente o recibo devido a uma conexão quebrada com o cartão. Corrigir o cartão para corresponder o recibo.`;
+ ? `Não é possível corresponder o recibo automaticamente devido a uma conexão de cartão com problema. Marque como dinheiro para ignorar ou corrija o cartão para corresponder o recibo.`
+ : `Não foi possível conciliar automaticamente o recibo devido a uma conexão quebrada do cartão. Corrija o cartão para conciliar o recibo.`;
}
if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
return isAdmin
- ? `Conexão bancária interrompida. Reconectar para corresponder ao recibo`
- : 'Conexão bancária interrompida. Peça para um administrador reconectar para corresponder ao recibo.';
+ ? `Conexão bancária interrompida. Reconectar para combinar com o recibo`
+ : 'Conexão bancária interrompida. Peça para um administrador reconectar para coincidir com o recibo.';
}
if (!isTransactionOlderThan7Days) {
- return isAdmin ? `Peça para ${member} marcar como dinheiro ou aguarde 7 dias e tente novamente` : 'Aguardando associação com a transação do cartão.';
+ return isAdmin ? `Peça para ${member} marcar como dinheiro ou aguarde 7 dias e tente novamente` : 'Aguardando combinação com a transação do cartão.';
}
return '';
},
brokenConnection530Error: 'Recibo pendente devido à conexão bancária interrompida',
+ brokenConnection531Error: 'Não foi possível associar automaticamente o recibo devido a um problema temporário no banco. Tente novamente mais tarde.',
adminBrokenConnectionError: ({workspaceCompanyCardRoute}: {workspaceCompanyCardRoute: string}) =>
`Recibo pendente devido a uma conexão bancária interrompida. Resolva em Cartões corporativos.`,
memberBrokenConnectionError: 'Recibo pendente devido à conexão bancária com problemas. Peça a um administrador do workspace para resolver.',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 6ce4f2e7ce4e..effe90a8ad38 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -9689,7 +9689,7 @@ ${reportName}`,
isAdmin: boolean,
isTransactionOlderThan7Days: boolean,
member?: string,
- rterType?: string,
+ rterType?: ValueOf,
companyCardPageURL?: string,
connectionLink?: string,
isPersonalCard?: boolean,
@@ -9698,34 +9698,38 @@ ${reportName}`,
if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
return '由于银行连接中断,无法自动匹配收据。';
}
+ if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_531) {
+ return '由于临时的银行问题,无法自动匹配收据。请稍后重试。';
+ }
if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_REAUTH) {
if (isPersonalCard) {
if (!connectionLink) {
- return '由于您的银行连接需要重新验证,无法自动匹配收据。';
+ return '无法自动匹配收据,因为您的银行连接需要重新验证。';
}
return isMarkAsCash
- ? `由于您的银行连接需要重新验证,无法自动匹配收据。标记为现金以忽略,或重新连接以匹配收据。`
- : `由于您的银行连接需要重新验证,无法自动匹配收据。请重新连接以匹配该收据。`;
+ ? `无法自动匹配收据,因为你的银行连接需要重新验证。标记为现金以忽略,或重新连接来匹配收据。`
+ : `无法自动匹配收据,因为您的银行连接需要重新验证。请重新连接以匹配该收据。`;
}
- return isAdmin ? `银行连接需要重新验证。重新连接以匹配收据` : '银行连接需要重新验证。请让管理员重新连接以匹配收据。';
+ return isAdmin ? `银行连接需要重新验证。重新连接以匹配收据` : '银行连接需要重新验证。请联系管理员重新连接以匹配收据。';
}
if (isPersonalCard && (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION || brokenBankConnection)) {
if (!connectionLink) {
return '由于银行连接中断,无法自动匹配收据。';
}
return isMarkAsCash
- ? `由于银行卡连接异常,无法自动匹配收据。标记为现金以忽略,或修复银行卡以匹配收据。`
- : `由于银行卡连接异常,无法自动匹配收据。请修复银行卡以匹配该收据。`;
+ ? `由于卡片连接异常,无法自动匹配收据。标记为现金以忽略,或修复卡片以匹配收据。`
+ : `由于卡片连接中断,无法自动匹配收据。请修复此卡以匹配收据。`;
}
if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
return isAdmin ? `银行连接已断开。重新连接以匹配收据` : '银行连接已断开。请让管理员重新连接以匹配收据。';
}
if (!isTransactionOlderThan7Days) {
- return isAdmin ? `请让 ${member} 将其标记为现金,或等待 7 天后再试` : '正在等待与信用卡交易合并。';
+ return isAdmin ? `请让 ${member} 将其标记为现金,或等待 7 天后重试` : '正在等待与卡片交易合并。';
}
return '';
},
brokenConnection530Error: '由于银行连接中断,收据待处理',
+ brokenConnection531Error: '由于临时的银行问题,无法自动匹配收据。请稍后重试。',
adminBrokenConnectionError: ({workspaceCompanyCardRoute}: {workspaceCompanyCardRoute: string}) =>
`由于银行连接中断,收据暂时待处理。请前往公司卡中解决。`,
memberBrokenConnectionError: '由于银行连接中断,收据处于待处理状态。请联系工作区管理员解决。',
diff --git a/src/libs/TransactionUtils/index.ts b/src/libs/TransactionUtils/index.ts
index 411f6308beb3..35529422e300 100644
--- a/src/libs/TransactionUtils/index.ts
+++ b/src/libs/TransactionUtils/index.ts
@@ -8,7 +8,7 @@ import type {CurrencyListActionsContextType} from '@hooks/useCurrencyList';
import type {MergeDuplicatesParams} from '@libs/API/parameters';
import {convertAttendeesToArray, normalizeAttendees} from '@libs/AttendeeUtils';
-import {isTravelCardTransaction} from '@libs/CardUtils';
+import {isPersonalCard, isTravelCardTransaction} from '@libs/CardUtils';
import {getCategoryDefaultTaxRate, isCategoryMissing} from '@libs/CategoryUtils';
import {convertToBackendAmount} from '@libs/CurrencyUtils';
import type {MachineDateFormat} from '@libs/DateUtils';
@@ -2065,18 +2065,40 @@ function isBrokenConnectionViolation(violation: TransactionViolation) {
violation.name === CONST.VIOLATIONS.RTER &&
(violation.data?.rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION ||
violation.data?.rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530 ||
+ violation.data?.rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_531 ||
violation.data?.rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_REAUTH)
);
}
/**
- * Finds the broken-connection violation that drives the money-request header status and its personal-card
- * suppression. It intentionally excludes the `brokenCardConnection530` subtype (scraper being fixed on
- * Expensify's side): 530 keeps its own dedicated `brokenConnection530Error` header regardless of card type,
- * so it must never be swallowed by the personal-card suppression.
+ * Suppresses the report-level status only when every broken connection belongs to a personal card.
+ * Reports with company-card or retry-later violations must retain a status so their required action is visible.
*/
-function getBrokenConnectionViolation(transactionViolations: TransactionViolation[] | undefined): TransactionViolation | undefined {
- return transactionViolations?.find((violation) => isBrokenConnectionViolation(violation) && violation.data?.rterType !== CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530);
+function shouldSuppressBrokenConnectionStatus(brokenConnectionViolations: TransactionViolation[], cardList: OnyxEntry) {
+ return (
+ brokenConnectionViolations.length > 0 &&
+ brokenConnectionViolations.every((violation) => {
+ if (violation.data?.rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530 || violation.data?.rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_531) {
+ return false;
+ }
+
+ const cardID = violation.data?.cardID;
+ const card = cardID ? cardList?.[cardID] : undefined;
+ return !!card && isPersonalCard(card);
+ })
+ );
+}
+
+/** Returns a report transaction that has a broken connection status which must remain visible. */
+function getUnsuppressibleBrokenConnectionTransactionID(
+ transactions: Transaction[],
+ transactionViolations: OnyxCollection,
+ cardList: OnyxEntry,
+): string | undefined {
+ return transactions.find((transaction) => {
+ const brokenConnectionViolations = (transactionViolations?.[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transaction.transactionID}`] ?? []).filter(isBrokenConnectionViolation);
+ return brokenConnectionViolations.length > 0 && !shouldSuppressBrokenConnectionStatus(brokenConnectionViolations, cardList);
+ })?.transactionID;
}
function shouldShowBrokenConnectionViolationInternal(brokenConnectionViolations: TransactionViolation[], report: OnyxEntry, policy: OnyxEntry) {
@@ -3762,7 +3784,7 @@ export {
hasMissingSmartscanFields,
hasMissingSmartscanFieldsForRBR,
hasPendingRTERViolation,
- getBrokenConnectionViolation,
+ getUnsuppressibleBrokenConnectionTransactionID,
hasAnyPendingRTERViolation,
hasValidModifiedAmount,
getNegatedAmountTransaction,
@@ -3779,6 +3801,8 @@ export {
hasSubmissionBlockingViolationInReport,
hasSubmissionBlockingViolations,
hasCustomUnitOutOfPolicyViolation,
+ isBrokenConnectionViolation,
+ shouldSuppressBrokenConnectionStatus,
shouldShowBrokenConnectionViolation,
shouldShowBrokenConnectionViolationForMultipleTransactions,
hasNoticeTypeViolation,
diff --git a/tests/ui/BrokenConnectionDescriptionTest.tsx b/tests/ui/BrokenConnectionDescriptionTest.tsx
new file mode 100644
index 000000000000..0b51d66defdb
--- /dev/null
+++ b/tests/ui/BrokenConnectionDescriptionTest.tsx
@@ -0,0 +1,81 @@
+import {render, screen} from '@testing-library/react-native';
+
+import BrokenConnectionDescription from '@components/BrokenConnectionDescription';
+import Text from '@components/Text';
+
+import CONST from '@src/CONST';
+import type {TransactionViolations} from '@src/types/onyx';
+
+import React from 'react';
+
+const mockUseTransactionViolations = jest.fn();
+const mockTranslate = jest.fn((key: string) => {
+ if (key === 'violations.brokenConnection530Error') {
+ return 'Receipt pending due to broken bank connection';
+ }
+ if (key === 'violations.brokenConnection531Error') {
+ return "Can't auto-match receipt due to a temporary bank issue. Please try again later.";
+ }
+ return key;
+});
+
+jest.mock('@hooks/useTransactionViolations', () => ({
+ __esModule: true,
+ default: (...args: unknown[]) => mockUseTransactionViolations(...args),
+}));
+jest.mock('@hooks/useEnvironment', () => jest.fn(() => ({environmentURL: ''})));
+jest.mock('@hooks/useLocalize', () => ({
+ __esModule: true,
+ default: () => ({translate: mockTranslate}),
+}));
+
+const renderDescription = () =>
+ render(
+
+
+ ,
+ );
+
+describe('BrokenConnectionDescription', () => {
+ afterEach(() => {
+ mockUseTransactionViolations.mockReset();
+ mockTranslate.mockClear();
+ });
+
+ it('shows the temporary retry-later message for a 531 broken card connection', () => {
+ mockUseTransactionViolations.mockReturnValue([
+ {
+ name: 'rter',
+ type: 'violation',
+ data: {rterType: CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_531},
+ },
+ ] as TransactionViolations);
+
+ renderDescription();
+
+ expect(screen.getByText("Can't auto-match receipt due to a temporary bank issue. Please try again later.")).toBeTruthy();
+ });
+
+ it('prefers the 530 message when both 530 and 531 broken connections are present', () => {
+ mockUseTransactionViolations.mockReturnValue([
+ {
+ name: 'rter',
+ type: 'violation',
+ data: {rterType: CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_531},
+ },
+ {
+ name: 'rter',
+ type: 'violation',
+ data: {rterType: CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530},
+ },
+ ] as TransactionViolations);
+
+ renderDescription();
+
+ expect(screen.getByText('Receipt pending due to broken bank connection')).toBeTruthy();
+ });
+});
diff --git a/tests/unit/TransactionUtilsTest.ts b/tests/unit/TransactionUtilsTest.ts
index d6145cfb265d..0f3061e6a28f 100644
--- a/tests/unit/TransactionUtilsTest.ts
+++ b/tests/unit/TransactionUtilsTest.ts
@@ -1656,6 +1656,14 @@ describe('TransactionUtils', () => {
expect(showBrokenConnectionViolation).toBe(true);
});
+ it('should return true for a 531 (temporary, retry later) broken connection violation', () => {
+ const policy = createMock({role: CONST.POLICY.ROLE.USER});
+ const transactionViolations = [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.RTER, data: {rterType: CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_531}}];
+ const showBrokenConnectionViolation = shouldShowBrokenConnectionViolation(undefined, policy, transactionViolations);
+
+ expect(showBrokenConnectionViolation).toBe(true);
+ });
+
it('should return true when a re-auth broken connection violation exists and the user is the policy member', () => {
const policy = createMock({role: CONST.POLICY.ROLE.USER});
const transactionViolations = [{type: CONST.VIOLATION_TYPES.VIOLATION, name: CONST.VIOLATIONS.RTER, data: {rterType: CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_REAUTH}}];
diff --git a/tests/unit/ViolationUtilsTest.ts b/tests/unit/ViolationUtilsTest.ts
index 153b913e8d33..59e3f7111ea3 100644
--- a/tests/unit/ViolationUtilsTest.ts
+++ b/tests/unit/ViolationUtilsTest.ts
@@ -3472,6 +3472,14 @@ const brokenCardConnection530Violation: TransactionViolation = {
},
};
+const brokenCardConnection531Violation: TransactionViolation = {
+ name: CONST.VIOLATIONS.RTER,
+ type: CONST.VIOLATION_TYPES.VIOLATION,
+ data: {
+ rterType: CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_531,
+ },
+};
+
const brokenCardConnectionReauthViolation: TransactionViolation = {
name: CONST.VIOLATIONS.RTER,
type: CONST.VIOLATION_TYPES.VIOLATION,
@@ -3520,6 +3528,14 @@ describe('getViolationTranslation', () => {
);
});
+ it('should return the temporary retry-later message for a 531 broken card connection', async () => {
+ IntlStore.load(CONST.LOCALES.EN);
+ await waitForBatchedUpdates();
+ expect(ViolationsUtils.getViolationTranslation({dateFnsLocale: undefined, violation: brokenCardConnection531Violation, translate: translateLocal, convertToDisplayString})).toBe(
+ "Can't auto-match receipt due to a temporary bank issue. Please try again later.",
+ );
+ });
+
describe('increasedDistance violation', () => {
const increasedDistanceViolation: TransactionViolation = {
name: CONST.VIOLATIONS.INCREASED_DISTANCE,
diff --git a/tests/unit/useMoneyReportHeaderStatusBarTest.ts b/tests/unit/useMoneyReportHeaderStatusBarTest.ts
new file mode 100644
index 000000000000..cc6f42964e62
--- /dev/null
+++ b/tests/unit/useMoneyReportHeaderStatusBarTest.ts
@@ -0,0 +1,54 @@
+import {getUnsuppressibleBrokenConnectionTransactionID, shouldSuppressBrokenConnectionStatus} from '@libs/TransactionUtils';
+
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {Card, CardList, Transaction, TransactionViolation, TransactionViolations} from '@src/types/onyx';
+
+import createMock from '../utils/createMock';
+
+describe('shouldSuppressBrokenConnectionStatus', () => {
+ const personalCardID = 1;
+ const personalCardList = createMock({[personalCardID]: createMock({fundID: '0'})});
+ const personalBrokenConnection = createMock({
+ type: CONST.VIOLATION_TYPES.VIOLATION,
+ name: CONST.VIOLATIONS.RTER,
+ data: {
+ rterType: CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION,
+ cardID: personalCardID,
+ },
+ });
+
+ it('does not suppress a report with a temporary retry-later violation', () => {
+ const temporaryBrokenConnection = createMock({
+ type: CONST.VIOLATION_TYPES.VIOLATION,
+ name: CONST.VIOLATIONS.RTER,
+ data: {
+ rterType: CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_531,
+ },
+ });
+
+ expect(shouldSuppressBrokenConnectionStatus([personalBrokenConnection, temporaryBrokenConnection], personalCardList)).toBe(false);
+ });
+
+ it('selects the temporary retry-later transaction instead of a preceding personal-card violation', () => {
+ const personalTransaction = createMock({transactionID: '1'});
+ const temporaryTransaction = createMock({transactionID: '2'});
+ const temporaryBrokenConnection = createMock({
+ type: CONST.VIOLATION_TYPES.VIOLATION,
+ name: CONST.VIOLATIONS.RTER,
+ data: {
+ rterType: CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_531,
+ },
+ });
+ const transactionViolations: Record = {
+ [`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${personalTransaction.transactionID}`]: [personalBrokenConnection],
+ [`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${temporaryTransaction.transactionID}`]: [temporaryBrokenConnection],
+ };
+
+ expect(getUnsuppressibleBrokenConnectionTransactionID([personalTransaction, temporaryTransaction], transactionViolations, personalCardList)).toBe(temporaryTransaction.transactionID);
+ });
+
+ it('suppresses a report only when all broken-connection violations are on personal cards', () => {
+ expect(shouldSuppressBrokenConnectionStatus([personalBrokenConnection], personalCardList)).toBe(true);
+ });
+});