From cba999bd6ddfded862bab51ae4715a32c282368f Mon Sep 17 00:00:00 2001
From: Samran Ahmed <samranahmed03@gmail.com>
Date: Mon, 3 Nov 2025 19:39:44 +0500
Subject: [PATCH 01/10] update: rter violation to include company card page URL

---
 src/libs/Violations/ViolationsUtils.ts | 4 ++--
 src/types/onyx/TransactionViolation.ts | 3 +++
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/libs/Violations/ViolationsUtils.ts b/src/libs/Violations/ViolationsUtils.ts
index 51d479b13726..a6a6b00e052d 100644
--- a/src/libs/Violations/ViolationsUtils.ts
+++ b/src/libs/Violations/ViolationsUtils.ts
@@ -472,7 +472,6 @@ const ViolationsUtils = {
         const {
             brokenBankConnection = false,
             isAdmin = false,
-            email,
             isTransactionOlderThan7Days = false,
             member,
             category,
@@ -486,6 +485,7 @@ const ViolationsUtils = {
             rterType,
             message = '',
             errorIndexes = [],
+            companyCardPageURL = '',
         } = violation.data ?? {};
 
         switch (violation.name) {
@@ -547,10 +547,10 @@ const ViolationsUtils = {
                 return translate('violations.rter', {
                     brokenBankConnection,
                     isAdmin,
-                    email,
                     isTransactionOlderThan7Days,
                     member,
                     rterType,
+                    companyCardPageURL,
                 });
             case 'smartscanFailed':
                 return translate('violations.smartscanFailed', {canEdit});
diff --git a/src/types/onyx/TransactionViolation.ts b/src/types/onyx/TransactionViolation.ts
index e0e0ee79f21e..a78f4ce3391f 100644
--- a/src/types/onyx/TransactionViolation.ts
+++ b/src/types/onyx/TransactionViolation.ts
@@ -103,6 +103,9 @@ type TransactionViolationData = {
 
     /** Comment that triggered the violation */
     comment?: string;
+
+    /** URL to the company cards page for reconnecting broken bank connections */
+    companyCardPageURL?: string;
 };
 
 /** Model of a transaction violation */

From 09521cb3f903afd6652ce9dff80277a0a7903ec0 Mon Sep 17 00:00:00 2001
From: Samran Ahmed <samranahmed03@gmail.com>
Date: Mon, 3 Nov 2025 19:40:45 +0500
Subject: [PATCH 02/10] update: copy for rter violation in all locales

---
 src/languages/de.ts      | 6 +++---
 src/languages/en.ts      | 6 ++++--
 src/languages/es.ts      | 6 +++---
 src/languages/fr.ts      | 6 +++---
 src/languages/it.ts      | 6 +++---
 src/languages/ja.ts      | 6 ++++--
 src/languages/nl.ts      | 6 +++---
 src/languages/params.ts  | 2 +-
 src/languages/pl.ts      | 6 +++---
 src/languages/pt-BR.ts   | 6 +++---
 src/languages/zh-hans.ts | 4 ++--
 11 files changed, 32 insertions(+), 28 deletions(-)

diff --git a/src/languages/de.ts b/src/languages/de.ts
index 943762000a90..24353516c272 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -6822,14 +6822,14 @@ ${amount} für ${merchant} - ${date}`,
         },
         customRules: ({message}: ViolationsCustomRulesParams) => message,
         reviewRequired: 'Überprüfung erforderlich',
-        rter: ({brokenBankConnection, email, isAdmin, isTransactionOlderThan7Days, member, rterType}: ViolationsRterParams) => {
+        rter: ({brokenBankConnection, isAdmin, isTransactionOlderThan7Days, member, rterType, companyCardPageURL}: ViolationsRterParams) => {
             if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
                 return 'Kassenbon kann aufgrund einer unterbrochenen Bankverbindung nicht automatisch zugeordnet werden.';
             }
             if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
                 return isAdmin
-                    ? `Kassenbon kann aufgrund einer unterbrochenen Bankverbindung, die ${email} beheben muss, nicht automatisch zugeordnet werden.`
-                    : 'Kassenbon kann aufgrund einer unterbrochenen Bankverbindung nicht automatisch zugeordnet werden.';
+                    ? `Bankverbindung unterbrochen. <a href="${companyCardPageURL}">Jetzt wieder verbinden, um den Beleg zuzuordnen</a>`
+                    : 'Bankverbindung unterbrochen. Bitte einen Admin bitten, sie wieder zu verbinden, um den Beleg zuzuordnen.';
             }
             if (!isTransactionOlderThan7Days) {
                 return isAdmin
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 0678c58f4565..b4d0dcab7bfd 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -6779,12 +6779,14 @@ const translations = {
         },
         customRules: ({message}: ViolationsCustomRulesParams) => message,
         reviewRequired: 'Review required',
-        rter: ({brokenBankConnection, email, isAdmin, isTransactionOlderThan7Days, member, rterType}: ViolationsRterParams) => {
+        rter: ({brokenBankConnection, isAdmin, isTransactionOlderThan7Days, member, rterType, companyCardPageURL}: ViolationsRterParams) => {
             if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
                 return "Can't auto-match receipt due to broken bank connection";
             }
             if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
-                return isAdmin ? `Can't auto-match receipt due to broken bank connection which ${email} needs to fix` : "Can't auto-match receipt due to broken bank connection";
+                return isAdmin
+                    ? `Bank connection broken. <a href="${companyCardPageURL}">Reconnect to match receipt</a>`
+                    : 'Bank connection broken. Ask an admin to reconnect to match receipt.';
             }
             if (!isTransactionOlderThan7Days) {
                 return isAdmin ? `Ask ${member} to mark as a cash or wait 7 days and try again` : 'Awaiting merge with card transaction.';
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 49079d36b4cf..c1244846796a 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -7269,14 +7269,14 @@ ${amount} para ${merchant} - ${date}`,
         },
         customRules: ({message}: ViolationsCustomRulesParams) => message,
         reviewRequired: 'Revisión requerida',
-        rter: ({brokenBankConnection, isAdmin, email, isTransactionOlderThan7Days, member, rterType}: ViolationsRterParams) => {
+        rter: ({brokenBankConnection, isAdmin, isTransactionOlderThan7Days, member, rterType, companyCardPageURL}: ViolationsRterParams) => {
             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.';
             }
             if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
                 return isAdmin
-                    ? `No se puede adjuntar recibo debido a un problema con la conexión a tu banco que ${email} necesita arreglar`
-                    : 'No se puede adjuntar recibo debido a un problema con la conexión a tu banco';
+                    ? `Conexión bancaria interrumpida. <a href="${companyCardPageURL}">Vuelve a conectarte para emparejar el recibo</a>`
+                    : 'Conexión bancaria interrumpida. Pide a un administrador que la vuelva a conectar para emparejar el recibo.';
             }
             if (!isTransactionOlderThan7Days) {
                 return isAdmin
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 715dc45ae6f4..f401c4e6cb1e 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -6827,14 +6827,14 @@ ${amount} pour ${merchant} - ${date}`,
         },
         customRules: ({message}: ViolationsCustomRulesParams) => message,
         reviewRequired: 'Examen requis',
-        rter: ({brokenBankConnection, email, isAdmin, isTransactionOlderThan7Days, member, rterType}: ViolationsRterParams) => {
+        rter: ({brokenBankConnection, isAdmin, isTransactionOlderThan7Days, member, rterType, companyCardPageURL}: ViolationsRterParams) => {
             if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
                 return "Impossible de faire correspondre automatiquement le reçu en raison d'une connexion bancaire défectueuse.";
             }
             if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
                 return isAdmin
-                    ? `Impossible de faire correspondre automatiquement le reçu en raison d'une connexion bancaire défectueuse que ${email} doit corriger.`
-                    : "Impossible de faire correspondre automatiquement le reçu en raison d'une connexion bancaire défectueuse.";
+                    ? `Connexion bancaire interrompue. <a href="${companyCardPageURL}">Reconnecter pour associer le reçu</a>`
+                    : 'Connexion bancaire interrompue. Demandez à un administrateur de la reconnecter pour associer le reçu.';
             }
             if (!isTransactionOlderThan7Days) {
                 return isAdmin ? `Demandez à ${member} de marquer comme espèce ou attendez 7 jours et réessayez` : 'En attente de fusion avec la transaction par carte.';
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 7b75125a636e..650d0b4a5b07 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -6833,14 +6833,14 @@ ${amount} per ${merchant} - ${date}`,
         },
         customRules: ({message}: ViolationsCustomRulesParams) => message,
         reviewRequired: 'Revisione richiesta',
-        rter: ({brokenBankConnection, email, isAdmin, isTransactionOlderThan7Days, member, rterType}: ViolationsRterParams) => {
+        rter: ({brokenBankConnection, isAdmin, isTransactionOlderThan7Days, member, rterType, companyCardPageURL}: ViolationsRterParams) => {
             if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
                 return 'Impossibile associare automaticamente la ricevuta a causa di una connessione bancaria interrotta.';
             }
             if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
                 return isAdmin
-                    ? `Impossibile abbinare automaticamente la ricevuta a causa di una connessione bancaria interrotta che ${email} deve risolvere.`
-                    : 'Impossibile associare automaticamente la ricevuta a causa di una connessione bancaria interrotta.';
+                    ? `Connessione bancaria interrotta. <a href="${companyCardPageURL}">Riconnetti per abbinarla alla ricevuta</a>`
+                    : 'Connessione bancaria interrotta. Chiedi a un amministratore di riconnetterla per abbinare la ricevuta.';
             }
             if (!isTransactionOlderThan7Days) {
                 return isAdmin ? `Chiedi a ${member} di contrassegnarlo come contante o attendi 7 giorni e riprova` : 'In attesa di unione con la transazione della carta.';
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index cc792be36cc3..9a100d9e4f7c 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -6767,12 +6767,14 @@ ${date} - ${merchant}に${amount}`,
         },
         customRules: ({message}: ViolationsCustomRulesParams) => message,
         reviewRequired: 'レビューが必要です',
-        rter: ({brokenBankConnection, email, isAdmin, isTransactionOlderThan7Days, member, rterType}: ViolationsRterParams) => {
+        rter: ({brokenBankConnection, isAdmin, isTransactionOlderThan7Days, member, rterType, companyCardPageURL}: ViolationsRterParams) => {
             if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
                 return '銀行接続が切れているため、領収書を自動照合できません。';
             }
             if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
-                return isAdmin ? `${email}が修正する必要がある銀行接続の問題のため、領収書を自動マッチングできません。` : '銀行接続が切れているため、領収書を自動照合できません。';
+                return isAdmin
+                    ? `銀行接続が切断されています。<a href="${companyCardPageURL}">再接続して領収書を照合してください</a>`
+                    : '銀行接続が切断されています。領収書を照合するには管理者に再接続を依頼してください。';
             }
             if (!isTransactionOlderThan7Days) {
                 return isAdmin ? `${member}に現金としてマークするように依頼するか、7日間待って再試行してください。` : 'カード取引とのマージを待機中。';
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 53b3e9921439..646a39004094 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -6818,14 +6818,14 @@ ${amount} voor ${merchant} - ${date}`,
         },
         customRules: ({message}: ViolationsCustomRulesParams) => message,
         reviewRequired: 'Beoordeling vereist',
-        rter: ({brokenBankConnection, email, isAdmin, isTransactionOlderThan7Days, member, rterType}: ViolationsRterParams) => {
+        rter: ({brokenBankConnection, isAdmin, isTransactionOlderThan7Days, member, rterType, companyCardPageURL}: ViolationsRterParams) => {
             if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
                 return 'Kan bon niet automatisch koppelen vanwege verbroken bankverbinding.';
             }
             if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
                 return isAdmin
-                    ? `Kan ontvangst niet automatisch koppelen vanwege een verbroken bankverbinding die ${email} moet herstellen.`
-                    : 'Kan bon niet automatisch koppelen vanwege verbroken bankverbinding.';
+                    ? `Bankverbinding verbroken. <a href="${companyCardPageURL}">Opnieuw verbinden om bon te koppelen</a>`
+                    : 'Bankverbinding verbroken. Vraag een beheerder 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 samenvoeging met kaarttransactie.';
diff --git a/src/languages/params.ts b/src/languages/params.ts
index 6ee4cffa34ff..f63608742253 100644
--- a/src/languages/params.ts
+++ b/src/languages/params.ts
@@ -326,10 +326,10 @@ type ViolationsCustomRulesParams = {message: string};
 type ViolationsRterParams = {
     brokenBankConnection: boolean;
     isAdmin: boolean;
-    email?: string;
     isTransactionOlderThan7Days: boolean;
     member?: string;
     rterType?: ValueOf<typeof CONST.RTER_VIOLATION_TYPES>;
+    companyCardPageURL: string;
 };
 
 type ViolationsTagOutOfPolicyParams = {tagName?: string} | undefined;
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 40dda5d0bd6d..10be8808f6eb 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -6805,14 +6805,14 @@ ${amount} dla ${merchant} - ${date}`,
         },
         customRules: ({message}: ViolationsCustomRulesParams) => message,
         reviewRequired: 'Wymagana recenzja',
-        rter: ({brokenBankConnection, email, isAdmin, isTransactionOlderThan7Days, member, rterType}: ViolationsRterParams) => {
+        rter: ({brokenBankConnection, isAdmin, isTransactionOlderThan7Days, member, rterType, companyCardPageURL}: ViolationsRterParams) => {
             if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
                 return 'Nie można automatycznie dopasować paragonu z powodu przerwanego połączenia z bankiem.';
             }
             if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
                 return isAdmin
-                    ? `Nie można automatycznie dopasować paragonu z powodu zerwanego połączenia z bankiem, które ${email} musi naprawić.`
-                    : 'Nie można automatycznie dopasować paragonu z powodu przerwanego połączenia z bankiem.';
+                    ? `Połączenie bankowe zostało przerwane. <a href="${companyCardPageURL}">Połącz ponownie, aby dopasować paragon</a>`
+                    : 'Połączenie bankowe zostało przerwane. Poproś administratora o ponowne połączenie, aby dopasować paragon.';
             }
             if (!isTransactionOlderThan7Days) {
                 return isAdmin ? `Poproś ${member}, aby oznaczył jako gotówkę lub poczekaj 7 dni i spróbuj ponownie.` : 'Oczekiwanie na połączenie z transakcją kartową.';
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 67cc651980fb..e7ff64375175 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -6813,14 +6813,14 @@ ${amount} para ${merchant} - ${date}`,
         },
         customRules: ({message}: ViolationsCustomRulesParams) => message,
         reviewRequired: 'Revisão necessária',
-        rter: ({brokenBankConnection, email, isAdmin, isTransactionOlderThan7Days, member, rterType}: ViolationsRterParams) => {
+        rter: ({brokenBankConnection, isAdmin, isTransactionOlderThan7Days, member, rterType, companyCardPageURL}: ViolationsRterParams) => {
             if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
                 return 'Não é possível associar automaticamente o recibo devido a uma conexão bancária interrompida.';
             }
             if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
                 return isAdmin
-                    ? `Não é possível associar automaticamente o recibo devido a uma conexão bancária interrompida que ${email} precisa corrigir.`
-                    : 'Não é possível associar automaticamente o recibo devido a uma conexão bancária interrompida.';
+                    ? `Conexão bancária interrompida. <a href="${companyCardPageURL}">Reconectar para associar o recibo</a>`
+                    : 'Conexão bancária interrompida. Peça a um administrador para reconectar e associar o recibo.';
             }
             if (!isTransactionOlderThan7Days) {
                 return isAdmin ? `Peça a ${member} para marcar como dinheiro ou espere 7 dias e tente novamente.` : 'Aguardando a fusão com a transação do cartão.';
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 73f88ff1671a..2bcca252b07e 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -6673,12 +6673,12 @@ ${merchant}的${amount} - ${date}`,
         },
         customRules: ({message}: ViolationsCustomRulesParams) => message,
         reviewRequired: '需要审核',
-        rter: ({brokenBankConnection, email, isAdmin, isTransactionOlderThan7Days, member, rterType}: ViolationsRterParams) => {
+        rter: ({brokenBankConnection, isAdmin, isTransactionOlderThan7Days, member, rterType, companyCardPageURL}: ViolationsRterParams) => {
             if (rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530) {
                 return '由于银行连接中断，无法自动匹配收据。';
             }
             if (brokenBankConnection || rterType === CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION) {
-                return isAdmin ? `由于银行连接中断，无法自动匹配收据，需要${email}进行修复。` : '由于需要修复的银行连接中断，无法自动匹配收据。';
+                return isAdmin ? `银行连接已中断。<a href="${companyCardPageURL}">重新连接以匹配收据</a>` : '银行连接已中断。请联系管理员重新连接以匹配收据。';
             }
             if (!isTransactionOlderThan7Days) {
                 return isAdmin ? `请${member}标记为现金，或等待7天后再试一次。` : '正在等待与卡交易合并。';

From 7db803d1e209cf08dc0b6fc04d40ad8e343d6f21 Mon Sep 17 00:00:00 2001
From: Samran Ahmed <samranahmed03@gmail.com>
Date: Mon, 3 Nov 2025 20:30:41 +0500
Subject: [PATCH 03/10] update unit test to include companyCardPageURL

---
 src/languages/params.ts          | 2 +-
 src/libs/DebugUtils.ts           | 1 +
 tests/unit/ViolationUtilsTest.ts | 4 ++++
 3 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/languages/params.ts b/src/languages/params.ts
index f63608742253..752a7f7d81ba 100644
--- a/src/languages/params.ts
+++ b/src/languages/params.ts
@@ -329,7 +329,7 @@ type ViolationsRterParams = {
     isTransactionOlderThan7Days: boolean;
     member?: string;
     rterType?: ValueOf<typeof CONST.RTER_VIOLATION_TYPES>;
-    companyCardPageURL: string;
+    companyCardPageURL?: string;
 };
 
 type ViolationsTagOutOfPolicyParams = {tagName?: string} | undefined;
diff --git a/src/libs/DebugUtils.ts b/src/libs/DebugUtils.ts
index fc5139ec96fc..add2bc7c8ca4 100644
--- a/src/libs/DebugUtils.ts
+++ b/src/libs/DebugUtils.ts
@@ -1279,6 +1279,7 @@ function validateTransactionViolationDraftProperty(key: keyof TransactionViolati
                 field: 'string',
                 prohibitedExpenseRule: 'string',
                 comment: 'string',
+                companyCardPageURL: 'string',
             });
         case 'showInReview':
             return validateBoolean(value);
diff --git a/tests/unit/ViolationUtilsTest.ts b/tests/unit/ViolationUtilsTest.ts
index b5617e890864..6185c2fa84cd 100644
--- a/tests/unit/ViolationUtilsTest.ts
+++ b/tests/unit/ViolationUtilsTest.ts
@@ -658,11 +658,14 @@ const brokenCardConnection530Violation: TransactionViolation = {
 
 describe('getViolationTranslation', () => {
     it('should return the correct message for broken card connection violation', () => {
+        const testPolicyID = 'test-policy-123';
+        const companyCardPageURL = `workspaces/${testPolicyID}/company-cards`;
         const brokenCardConnectionViolationExpected = translateLocal('violations.rter', {
             brokenBankConnection: true,
             isAdmin: true,
             rterType: CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION,
             isTransactionOlderThan7Days: false,
+            companyCardPageURL,
         });
         expect(ViolationsUtils.getViolationTranslation(brokenCardConnectionViolation, translateLocal)).toBe(brokenCardConnectionViolationExpected);
         const brokenCardConnection530ViolationExpected = translateLocal('violations.rter', {
@@ -670,6 +673,7 @@ describe('getViolationTranslation', () => {
             isAdmin: false,
             rterType: CONST.RTER_VIOLATION_TYPES.BROKEN_CARD_CONNECTION_530,
             isTransactionOlderThan7Days: false,
+            companyCardPageURL,
         });
         expect(ViolationsUtils.getViolationTranslation(brokenCardConnection530Violation, translateLocal)).toBe(brokenCardConnection530ViolationExpected);
     });

From e19a99f39eae9891f4397ad2590b41480fe73868 Mon Sep 17 00:00:00 2001
From: Samran Ahmed <samranahmed03@gmail.com>
Date: Wed, 5 Nov 2025 21:16:16 +0500
Subject: [PATCH 04/10] pass companyCardPageURL as param

---
 src/components/TransactionItemRow/TransactionItemRowRBR.tsx | 5 +++++
 src/libs/DebugUtils.ts                                      | 1 -
 src/libs/Violations/ViolationsUtils.ts                      | 6 +++---
 src/types/onyx/TransactionViolation.ts                      | 3 ---
 4 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/src/components/TransactionItemRow/TransactionItemRowRBR.tsx b/src/components/TransactionItemRow/TransactionItemRowRBR.tsx
index ae0fc95984ed..0e8b99d29636 100644
--- a/src/components/TransactionItemRow/TransactionItemRowRBR.tsx
+++ b/src/components/TransactionItemRow/TransactionItemRowRBR.tsx
@@ -4,6 +4,7 @@ import {View} from 'react-native';
 import Icon from '@components/Icon';
 import {DotIndicator} from '@components/Icon/Expensicons';
 import RenderHTML from '@components/RenderHTML';
+import useEnvironment from '@hooks/useEnvironment';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useTheme from '@hooks/useTheme';
@@ -13,6 +14,7 @@ import {isSettled} from '@libs/ReportUtils';
 import ViolationsUtils from '@libs/Violations/ViolationsUtils';
 import variables from '@styles/variables';
 import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
 import type {Report, TransactionViolation} from '@src/types/onyx';
 import type Transaction from '@src/types/onyx/Transaction';
 
@@ -37,9 +39,11 @@ function TransactionItemRowRBR({transaction, violations, report, containerStyles
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const theme = useTheme();
+    const {environmentURL} = useEnvironment();
     const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transaction.reportID}`, {
         canBeMissing: true,
     });
+    const companyCardPageURL = `${environmentURL}/${ROUTES.WORKSPACE_COMPANY_CARDS.getRoute(report?.policyID)}`;
     const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${report?.policyID}`, {canBeMissing: true});
     const transactionThreadId = reportActions ? getIOUActionForTransactionID(Object.values(reportActions ?? {}), transaction.transactionID)?.childReportID : undefined;
     const [transactionThreadActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadId}`, {
@@ -53,6 +57,7 @@ function TransactionItemRowRBR({transaction, violations, report, containerStyles
         missingFieldError,
         Object.values(transactionThreadActions ?? {}),
         policyTags,
+        companyCardPageURL,
     );
 
     return (
diff --git a/src/libs/DebugUtils.ts b/src/libs/DebugUtils.ts
index 591c0d47fab0..80830b0579eb 100644
--- a/src/libs/DebugUtils.ts
+++ b/src/libs/DebugUtils.ts
@@ -1277,7 +1277,6 @@ function validateTransactionViolationDraftProperty(key: keyof TransactionViolati
                 field: 'string',
                 prohibitedExpenseRule: 'string',
                 comment: 'string',
-                companyCardPageURL: 'string',
             });
         case 'showInReview':
             return validateBoolean(value);
diff --git a/src/libs/Violations/ViolationsUtils.ts b/src/libs/Violations/ViolationsUtils.ts
index a6a6b00e052d..a806d04e8794 100644
--- a/src/libs/Violations/ViolationsUtils.ts
+++ b/src/libs/Violations/ViolationsUtils.ts
@@ -468,7 +468,7 @@ const ViolationsUtils = {
      * possible values could be either translation keys that resolve to  strings or translation keys that resolve to
      * functions.
      */
-    getViolationTranslation(violation: TransactionViolation, translate: LocaleContextProps['translate'], canEdit = true, tags?: PolicyTagLists): string {
+    getViolationTranslation(violation: TransactionViolation, translate: LocaleContextProps['translate'], canEdit = true, tags?: PolicyTagLists, companyCardPageURL?: string): string {
         const {
             brokenBankConnection = false,
             isAdmin = false,
@@ -485,7 +485,6 @@ const ViolationsUtils = {
             rterType,
             message = '',
             errorIndexes = [],
-            companyCardPageURL = '',
         } = violation.data ?? {};
 
         switch (violation.name) {
@@ -595,6 +594,7 @@ const ViolationsUtils = {
         missingFieldError?: string,
         transactionThreadActions?: ReportAction[],
         tags?: PolicyTagLists,
+        companyCardPageURL?: string,
     ): string {
         const errorMessages = extractErrorMessages(transaction?.errors ?? {}, transactionThreadActions?.filter((e) => !!e.errors) ?? [], translate);
 
@@ -604,7 +604,7 @@ const ViolationsUtils = {
             // Some violations end with a period already so lets make sure the connected messages have only single period between them
             // and end with a single dot.
             ...transactionViolations.map((violation) => {
-                const message = ViolationsUtils.getViolationTranslation(violation, translate, true, tags);
+                const message = ViolationsUtils.getViolationTranslation(violation, translate, true, tags, companyCardPageURL);
                 if (!message) {
                     return;
                 }
diff --git a/src/types/onyx/TransactionViolation.ts b/src/types/onyx/TransactionViolation.ts
index a78f4ce3391f..e0e0ee79f21e 100644
--- a/src/types/onyx/TransactionViolation.ts
+++ b/src/types/onyx/TransactionViolation.ts
@@ -103,9 +103,6 @@ type TransactionViolationData = {
 
     /** Comment that triggered the violation */
     comment?: string;
-
-    /** URL to the company cards page for reconnecting broken bank connections */
-    companyCardPageURL?: string;
 };
 
 /** Model of a transaction violation */

From 95af61b54650bbe0b3eb007852d05e0834caad08 Mon Sep 17 00:00:00 2001
From: Samran Ahmed <samranahmed03@gmail.com>
Date: Thu, 6 Nov 2025 17:13:49 +0500
Subject: [PATCH 05/10] fix: pass companyCardPageURL as param to
 getViolationTranslation

---
 .../ReportActionItem/MoneyRequestReceiptView.tsx    |  5 ++++-
 .../ReportActionItem/MoneyRequestView.tsx           |  6 +++++-
 .../TransactionPreviewContent.tsx                   |  6 +++++-
 src/components/ViolationMessages.tsx                | 13 ++++++++++---
 4 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/src/components/ReportActionItem/MoneyRequestReceiptView.tsx b/src/components/ReportActionItem/MoneyRequestReceiptView.tsx
index 8878fcd57b2b..857d1e63001d 100644
--- a/src/components/ReportActionItem/MoneyRequestReceiptView.tsx
+++ b/src/components/ReportActionItem/MoneyRequestReceiptView.tsx
@@ -8,6 +8,7 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback';
 import ReceiptAudit, {ReceiptAuditMessages} from '@components/ReceiptAudit';
 import ReceiptEmptyState from '@components/ReceiptEmptyState';
 import useActiveRoute from '@hooks/useActiveRoute';
+import useEnvironment from '@hooks/useEnvironment';
 import useGetIOUReportFromReportAction from '@hooks/useGetIOUReportFromReportAction';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
@@ -97,6 +98,7 @@ function MoneyRequestReceiptView({
 }: MoneyRequestReceiptViewProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
+    const {environmentURL} = useEnvironment();
     const {shouldUseNarrowLayout} = useResponsiveLayout();
     const {getReportRHPActiveRoute} = useActiveRoute();
     const parentReportID = report?.parentReportID;
@@ -137,6 +139,7 @@ function MoneyRequestReceiptView({
     const isReportArchived = useReportIsArchived(report?.reportID);
     const isEditable = !!canUserPerformWriteActionReportUtils(report, isReportArchived) && !readonly;
     const canEdit = isMoneyRequestAction(parentReportAction) && canEditMoneyRequest(parentReportAction, isChatReportArchived, moneyRequestReport, policy, transaction) && isEditable;
+    const companyCardPageURL = `${environmentURL}/${ROUTES.WORKSPACE_COMPANY_CARDS.getRoute(report?.policyID)}`;
 
     const canEditReceipt = isEditable && canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.RECEIPT, undefined, isChatReportArchived);
 
@@ -171,7 +174,7 @@ function MoneyRequestReceiptView({
             const isReceiptFieldViolation = receiptFieldViolationNames.includes(violation.name);
             const isReceiptImageViolation = receiptImageViolationNames.includes(violation.name);
             if (isReceiptFieldViolation || isReceiptImageViolation) {
-                const violationMessage = ViolationsUtils.getViolationTranslation(violation, translate, canEdit);
+                const violationMessage = ViolationsUtils.getViolationTranslation(violation, translate, canEdit, undefined, companyCardPageURL);
                 allViolations.push(violationMessage);
                 if (isReceiptImageViolation) {
                     imageViolations.push(violationMessage);
diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx
index 781089d1bad1..8f22eadb62de 100644
--- a/src/components/ReportActionItem/MoneyRequestView.tsx
+++ b/src/components/ReportActionItem/MoneyRequestView.tsx
@@ -14,6 +14,7 @@ import Text from '@components/Text';
 import ViolationMessages from '@components/ViolationMessages';
 import {WideRHPContext} from '@components/WideRHPContextProvider';
 import useActiveRoute from '@hooks/useActiveRoute';
+import useEnvironment from '@hooks/useEnvironment';
 import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
 import useOnyx from '@hooks/useOnyx';
@@ -129,6 +130,7 @@ function MoneyRequestView({
     const theme = useTheme();
     const StyleUtils = useStyleUtils();
     const {isOffline} = useNetwork();
+    const {environmentURL} = useEnvironment();
     const {translate, toLocaleDigit} = useLocalize();
     const {getReportRHPActiveRoute} = useActiveRoute();
     const [lastVisitedPath] = useOnyx(ONYXKEYS.LAST_VISITED_PATH, {canBeMissing: true});
@@ -246,6 +248,7 @@ function MoneyRequestView({
     const isReportArchived = useReportIsArchived(report?.reportID);
     const isEditable = !!canUserPerformWriteActionReportUtils(report, isReportArchived) && !readonly;
     const canEdit = isMoneyRequestAction(parentReportAction) && canEditMoneyRequest(parentReportAction, isChatReportArchived, moneyRequestReport, policy, transaction) && isEditable;
+    const companyCardPageURL = `${environmentURL}/${ROUTES.WORKSPACE_COMPANY_CARDS.getRoute(report?.policyID)}`;
     const {isExpenseSplit} = getOriginalTransactionWithSplitInfo(transaction);
     const isSplitAvailable = moneyRequestReport && transaction && isSplitAction(moneyRequestReport, [transaction], policy);
 
@@ -417,7 +420,7 @@ function MoneyRequestView({
                 const firstViolation = violations.at(0);
 
                 if (firstViolation) {
-                    return ViolationsUtils.getViolationTranslation(firstViolation, translate, canEdit);
+                    return ViolationsUtils.getViolationTranslation(firstViolation, translate, canEdit, undefined, companyCardPageURL);
                 }
             }
 
@@ -901,6 +904,7 @@ function MoneyRequestView({
                                     textStyle={[styles.ph0]}
                                     isLast
                                     canEdit={canEdit}
+                                    companyCardPageURL={companyCardPageURL}
                                 />
                             )}
                         </View>
diff --git a/src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx b/src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx
index 203e75adc811..96faf82f92d1 100644
--- a/src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx
+++ b/src/components/ReportActionItem/TransactionPreview/TransactionPreviewContent.tsx
@@ -10,6 +10,7 @@ import ReportActionItemImages from '@components/ReportActionItem/ReportActionIte
 import UserInfoCellsWithArrow from '@components/SelectionListWithSections/Search/UserInfoCellsWithArrow';
 import Text from '@components/Text';
 import TransactionPreviewSkeletonView from '@components/TransactionPreviewSkeletonView';
+import useEnvironment from '@hooks/useEnvironment';
 import useLocalize from '@hooks/useLocalize';
 import useOnyx from '@hooks/useOnyx';
 import useReportIsArchived from '@hooks/useReportIsArchived';
@@ -33,6 +34,7 @@ import ViolationsUtils from '@libs/Violations/ViolationsUtils';
 import variables from '@styles/variables';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
+import ROUTES from '@src/ROUTES';
 import type {TransactionPreviewContentProps} from './types';
 
 function TransactionPreviewContent({
@@ -61,6 +63,7 @@ function TransactionPreviewContent({
     const theme = useTheme();
     const styles = useThemeStyles();
     const {translate} = useLocalize();
+    const {environmentURL} = useEnvironment();
 
     const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`, {canBeMissing: true});
     const isParentPolicyExpenseChat = isPolicyExpenseChat(chatReport);
@@ -103,7 +106,8 @@ function TransactionPreviewContent({
     const firstViolation = violations.at(0);
     const isIOUActionType = isMoneyRequestAction(action);
     const canEdit = isIOUActionType && canEditMoneyRequest(action, isChatReportArchived, report, policy, transaction);
-    const violationMessage = firstViolation ? ViolationsUtils.getViolationTranslation(firstViolation, translate, canEdit) : undefined;
+    const companyCardPageURL = `${environmentURL}/${ROUTES.WORKSPACE_COMPANY_CARDS.getRoute(report?.policyID)}`;
+    const violationMessage = firstViolation ? ViolationsUtils.getViolationTranslation(firstViolation, translate, canEdit, undefined, companyCardPageURL) : undefined;
 
     const previewText = useMemo(
         () =>
diff --git a/src/components/ViolationMessages.tsx b/src/components/ViolationMessages.tsx
index ab0543f58011..48c73890e825 100644
--- a/src/components/ViolationMessages.tsx
+++ b/src/components/ViolationMessages.tsx
@@ -7,13 +7,20 @@ import ViolationsUtils from '@libs/Violations/ViolationsUtils';
 import type {TransactionViolation} from '@src/types/onyx';
 import Text from './Text';
 
-type ViolationMessagesProps = {violations: TransactionViolation[]; isLast?: boolean; containerStyle?: StyleProp<ViewStyle>; textStyle?: StyleProp<TextStyle>; canEdit: boolean};
+type ViolationMessagesProps = {
+    violations: TransactionViolation[];
+    isLast?: boolean;
+    containerStyle?: StyleProp<ViewStyle>;
+    textStyle?: StyleProp<TextStyle>;
+    canEdit: boolean;
+    companyCardPageURL?: string;
+};
 
-export default function ViolationMessages({violations, isLast, containerStyle, textStyle, canEdit}: ViolationMessagesProps) {
+export default function ViolationMessages({violations, isLast, containerStyle, textStyle, canEdit, companyCardPageURL}: ViolationMessagesProps) {
     const styles = useThemeStyles();
     const {translate} = useLocalize();
     const violationMessages = useMemo(
-        () => violations.map((violation) => [violation.name, ViolationsUtils.getViolationTranslation(violation, translate, canEdit)]),
+        () => violations.map((violation) => [violation.name, ViolationsUtils.getViolationTranslation(violation, translate, canEdit, undefined, companyCardPageURL)]),
         [canEdit, translate, violations],
     );
 

From 473b0697d623079d74e894468b69ed4ccda5ee79 Mon Sep 17 00:00:00 2001
From: Samran Ahmed <samranahmed03@gmail.com>
Date: Thu, 6 Nov 2025 17:58:30 +0500
Subject: [PATCH 06/10] fix lint

---
 src/components/ReportActionItem/MoneyRequestReceiptView.tsx | 2 +-
 src/components/ReportActionItem/MoneyRequestView.tsx        | 1 +
 src/components/ViolationMessages.tsx                        | 2 +-
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/components/ReportActionItem/MoneyRequestReceiptView.tsx b/src/components/ReportActionItem/MoneyRequestReceiptView.tsx
index fc1337519343..179877e70937 100644
--- a/src/components/ReportActionItem/MoneyRequestReceiptView.tsx
+++ b/src/components/ReportActionItem/MoneyRequestReceiptView.tsx
@@ -181,7 +181,7 @@ function MoneyRequestReceiptView({
             }
         }
         return [imageViolations, allViolations];
-    }, [transactionViolations, translate, canEdit]);
+    }, [transactionViolations, translate, canEdit, companyCardPageURL]);
 
     const receiptRequiredViolation = transactionViolations?.some((violation) => violation.name === CONST.VIOLATIONS.RECEIPT_REQUIRED);
     const customRulesViolation = transactionViolations?.some((violation) => violation.name === CONST.VIOLATIONS.CUSTOM_RULES);
diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx
index dffd5c08b60d..b2e9a81567f0 100644
--- a/src/components/ReportActionItem/MoneyRequestView.tsx
+++ b/src/components/ReportActionItem/MoneyRequestView.tsx
@@ -440,6 +440,7 @@ function MoneyRequestView({
             canEditMerchant,
             canEdit,
             isCustomUnitOutOfPolicy,
+            MoneyRequestView,
         ],
     );
 
diff --git a/src/components/ViolationMessages.tsx b/src/components/ViolationMessages.tsx
index 48c73890e825..77b17dd44fad 100644
--- a/src/components/ViolationMessages.tsx
+++ b/src/components/ViolationMessages.tsx
@@ -21,7 +21,7 @@ export default function ViolationMessages({violations, isLast, containerStyle, t
     const {translate} = useLocalize();
     const violationMessages = useMemo(
         () => violations.map((violation) => [violation.name, ViolationsUtils.getViolationTranslation(violation, translate, canEdit, undefined, companyCardPageURL)]),
-        [canEdit, translate, violations],
+        [canEdit, translate, violations, companyCardPageURL],
     );
 
     return (

From 800dfe43affad4fb8ddf281187cbb847532e618d Mon Sep 17 00:00:00 2001
From: Samran Ahmed <samranahmed03@gmail.com>
Date: Fri, 7 Nov 2025 09:41:09 +0500
Subject: [PATCH 07/10] fix lint

---
 src/components/ReportActionItem/MoneyRequestView.tsx | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx
index 72a1663ebaf7..f76ab5e17310 100644
--- a/src/components/ReportActionItem/MoneyRequestView.tsx
+++ b/src/components/ReportActionItem/MoneyRequestView.tsx
@@ -14,8 +14,8 @@ import Text from '@components/Text';
 import ViolationMessages from '@components/ViolationMessages';
 import {WideRHPContext} from '@components/WideRHPContextProvider';
 import useActiveRoute from '@hooks/useActiveRoute';
-import useEnvironment from '@hooks/useEnvironment';
 import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
+import useEnvironment from '@hooks/useEnvironment';
 import useLocalize from '@hooks/useLocalize';
 import useNetwork from '@hooks/useNetwork';
 import useOnyx from '@hooks/useOnyx';
@@ -466,6 +466,7 @@ function MoneyRequestView({
             canEdit,
             isCustomUnitOutOfPolicy,
             MoneyRequestView,
+            companyCardPageURL,
         ],
     );
 

From 4ffbe523e81c492d04a4b004a86aaeaebb0a3ba4 Mon Sep 17 00:00:00 2001
From: Samran Ahmed <samranahmed03@gmail.com>
Date: Fri, 7 Nov 2025 13:05:55 +0500
Subject: [PATCH 08/10] Update
 src/components/ReportActionItem/MoneyRequestView.tsx

Co-authored-by: DylanDylann <141406735+DylanDylann@users.noreply.github.com>
---
 src/components/ReportActionItem/MoneyRequestView.tsx | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx
index f76ab5e17310..7d8a26048c42 100644
--- a/src/components/ReportActionItem/MoneyRequestView.tsx
+++ b/src/components/ReportActionItem/MoneyRequestView.tsx
@@ -465,7 +465,6 @@ function MoneyRequestView({
             canEditMerchant,
             canEdit,
             isCustomUnitOutOfPolicy,
-            MoneyRequestView,
             companyCardPageURL,
         ],
     );

From 079826e91c28348a4b5ad7673880704ee18408cc Mon Sep 17 00:00:00 2001
From: Samran Ahmed <samranahmed03@gmail.com>
Date: Sat, 8 Nov 2025 09:59:46 +0500
Subject: [PATCH 09/10] add ViolationsRterParams

---
 src/languages/es.ts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/languages/es.ts b/src/languages/es.ts
index b61016aab0c0..1444f7843b37 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -1,6 +1,7 @@
 import {CONST as COMMON_CONST} from 'expensify-common';
 import CONST from '@src/CONST';
 import type en from './en';
+import {ViolationsRterParams} from './params';
 import type {TranslationDeepObject} from './types';
 
 /* eslint-disable max-len */

From 451fadf75b65608a675e0134ae2598dad835e1f1 Mon Sep 17 00:00:00 2001
From: Samran Ahmed <samranahmed03@gmail.com>
Date: Sat, 8 Nov 2025 10:23:54 +0500
Subject: [PATCH 10/10] fix lint

---
 src/languages/es.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/languages/es.ts b/src/languages/es.ts
index 1444f7843b37..c856ce389a0b 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -1,7 +1,7 @@
 import {CONST as COMMON_CONST} from 'expensify-common';
 import CONST from '@src/CONST';
 import type en from './en';
-import {ViolationsRterParams} from './params';
+import type {ViolationsRterParams} from './params';
 import type {TranslationDeepObject} from './types';
 
 /* eslint-disable max-len */
