Skip to content

Commit 630028f

Browse files
authored
Merge pull request Expensify#91886 from Expensify/beaman-vendor-matching-r1-app-phase-3
[Payment due @mkhutornyi] Vendor matching CC - R1: App Phase 3 (expense flow UI)
2 parents 29ceba3 + c512012 commit 630028f

30 files changed

Lines changed: 706 additions & 33 deletions

config/eslint/eslint.seatbelt.tsv

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1563,7 +1563,7 @@
15631563
"../../tests/actions/IOUTest/SplitTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 21
15641564
"../../tests/actions/IOUTest/TrackExpenseTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 10
15651565
"../../tests/actions/IOUTest/UpdateMoneyRequestTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 4
1566-
"../../tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 2
1566+
"../../tests/actions/IOUTest/UpdateMoneyRequestVendorTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 3
15671567
"../../tests/actions/MergeTransactionTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 10
15681568
"../../tests/actions/OnyxUpdateManagerTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 4
15691569
"../../tests/actions/PersonalDetailsTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 10
@@ -1767,7 +1767,7 @@
17671767
"../../tests/unit/MentionUserRendererTest.tsx" "@typescript-eslint/no-unsafe-type-assertion" 8
17681768
"../../tests/unit/MentionUtilsTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 4
17691769
"../../tests/unit/MiddlewareTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 20
1770-
"../../tests/unit/ModifiedExpenseMessageTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 5
1770+
"../../tests/unit/ModifiedExpenseMessageTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 6
17711771
"../../tests/unit/MoneyRequestReportTransactionListActiveTransactionIDsTest.tsx" "@typescript-eslint/no-unsafe-type-assertion" 5
17721772
"../../tests/unit/MoneyRequestReportUtilsTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 8
17731773
"../../tests/unit/MoneyRequestUtilsTest.ts" "@typescript-eslint/no-unsafe-type-assertion" 3

src/CONST/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1645,6 +1645,7 @@ const CONST = {
16451645
MARK_REIMBURSED_FROM_INTEGRATION: 'ACTIONMARKEDREIMBURSEDFROMINTEGRATION', // OldDot Action
16461646
MERGED_WITH_CASH_TRANSACTION: 'MERGEDWITHCASHTRANSACTION',
16471647
MODIFIED_EXPENSE: 'MODIFIEDEXPENSE',
1648+
CONCIERGE_AUTO_MATCH_VENDOR: 'CONCIERGEAUTOMATCHVENDOR',
16481649
MOVED: 'MOVED',
16491650
MOVED_TRANSACTION: 'MOVEDTRANSACTION',
16501651
UNREPORTED_TRANSACTION: 'UNREPORTEDTRANSACTION',

src/ROUTES.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1759,6 +1759,16 @@ const ROUTES = {
17591759
return getUrlWithBackToParam(`${action as string}/${iouType as string}/category/new/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}`, backTo);
17601760
},
17611761
},
1762+
MONEY_REQUEST_STEP_VENDOR: {
1763+
route: ':action/:iouType/vendor/:transactionID/:reportID/:reportActionID?',
1764+
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string | undefined, reportID: string | undefined, reportActionID?: string) => {
1765+
if (!transactionID || !reportID) {
1766+
Log.warn('Invalid transactionID or reportID is used to build the MONEY_REQUEST_STEP_VENDOR route');
1767+
}
1768+
1769+
return `${action as string}/${iouType as string}/vendor/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}` as const;
1770+
},
1771+
},
17621772
MONEY_REQUEST_STEP_DESTINATION: {
17631773
route: ':action/:iouType/destination/:transactionID/:reportID',
17641774
getRoute: (action: IOUAction, iouType: IOUType, transactionID: string, reportID: string, backTo = '') =>

src/SCREENS.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ const SCREENS = {
388388
STEP_WAYPOINT: 'Money_Request_Step_Waypoint',
389389
DYNAMIC_STEP_TAX_AMOUNT: 'Dynamic_Money_Request_Step_Tax_Amount',
390390
DYNAMIC_STEP_TAX_RATE: 'Dynamic_Money_Request_Step_Tax_Rate',
391+
STEP_VENDOR: 'Money_Request_Step_Vendor',
391392
RECEIPT_VIEW: 'Money_Request_Receipt_View',
392393
STEP_SEND_FROM: 'Money_Request_Step_Send_From',
393394
STEP_COMPANY_INFO: 'Money_Request_Step_Company_Info',

src/components/ReportActionItem/MoneyRequestView.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,10 @@ import {
6565
getLengthOfTag,
6666
getPerDiemCustomUnit,
6767
getPolicyByCustomUnitID,
68+
getQBOVendorByID,
6869
getTagLists,
6970
hasDependentTags as hasDependentTagsPolicyUtils,
71+
hasVendorFeature,
7072
isAttendeeTrackingEnabled,
7173
isGroupPolicyByType,
7274
isPolicyAccessible,
@@ -461,6 +463,10 @@ function MoneyRequestView({
461463
});
462464
const shouldShowAttendees = shouldShowAttendeesTransactionUtils(iouType, policy);
463465

466+
const transactionVendor = transaction?.comment?.vendor;
467+
const transactionVendorName = getQBOVendorByID(policy, transactionVendor?.externalID)?.name ?? '';
468+
const shouldShowVendor = hasVendorFeature(policy, isBetaEnabled(CONST.BETAS.VENDOR_MATCHING)) && !(updatedTransaction?.reimbursable ?? !!transactionReimbursable) && !isInvoice;
469+
464470
const tripID = getTripIDFromTransactionParentReportID(parentReport?.parentReportID);
465471
const shouldShowViewTripDetails = hasReservationList(transaction) && !!tripID;
466472

@@ -1159,6 +1165,26 @@ function MoneyRequestView({
11591165
/>
11601166
</OfflineWithFeedback>
11611167
)}
1168+
{shouldShowVendor && (
1169+
<OfflineWithFeedback pendingAction={getPendingFieldAction('vendor')}>
1170+
<MenuItemWithTopDescription
1171+
description={translate('common.vendor')}
1172+
title={transactionVendorName}
1173+
numberOfLinesTitle={2}
1174+
interactive={canEdit}
1175+
shouldShowRightIcon={canEdit}
1176+
titleStyle={styles.flex1}
1177+
onPress={() => {
1178+
if (!transactionThreadReport?.reportID) {
1179+
return;
1180+
}
1181+
Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_VENDOR.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction.transactionID, transactionThreadReport.reportID));
1182+
}}
1183+
brickRoadIndicator={getErrorForField('vendor') ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
1184+
errorText={getErrorForField('vendor')}
1185+
/>
1186+
</OfflineWithFeedback>
1187+
)}
11621188
{shouldShowTag && tagList}
11631189
{!!shouldShowCard && (
11641190
<OfflineWithFeedback pendingAction={getPendingFieldAction('cardID')}>

src/languages/de.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ const translations: TranslationDeepObject<typeof en> = {
314314
merchant: 'Händler',
315315
change: 'Ändern',
316316
category: 'Kategorie',
317+
vendor: 'Anbieter',
317318
report: 'Bericht',
318319
billable: 'Abrechenbar',
319320
nonBillable: 'Nicht abrechenbar',
@@ -1665,6 +1666,7 @@ const translations: TranslationDeepObject<typeof en> = {
16651666
},
16661667
correctRateError: 'Beheben Sie den Kursfehler und versuchen Sie es erneut.',
16671668
AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Erklären<sparkles-icon/></a>`,
1669+
conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge hat diese Ausgabe <strong>${vendorName}</strong> zugeordnet`,
16681670
duplicateNonDefaultWorkspacePerDiemError:
16691671
'Sie können Per-Diem-Ausgaben nicht über mehrere Workspaces hinweg duplizieren, da sich die Sätze zwischen den Workspaces unterscheiden können.',
16701672
rulesModifiedFields: {

src/languages/en.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ const translations = {
329329
merchant: 'Merchant',
330330
change: 'Change',
331331
category: 'Category',
332+
vendor: 'Vendor',
332333
report: 'Report',
333334
billable: 'Billable',
334335
nonBillable: 'Non-billable',
@@ -1725,6 +1726,7 @@ const translations = {
17251726
},
17261727
correctRateError: 'Fix the rate error and try again.',
17271728
AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Explain<sparkles-icon/></a>`,
1729+
conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge matched this expense to <strong>${vendorName}</strong>`,
17281730
rulesModifiedFields: {
17291731
reimbursable: (value: boolean) => (value ? 'marked the expense as "reimbursable"' : 'marked the expense as "non-reimbursable"'),
17301732
billable: (value: boolean) => (value ? 'marked the expense as "billable"' : 'marked the expense as "non-billable"'),

src/languages/es.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ const translations: TranslationDeepObject<typeof en> = {
270270
merchant: 'Comerciante',
271271
change: 'Cambio',
272272
category: 'Categoría',
273+
vendor: 'Proveedor',
273274
report: 'Informe',
274275
billable: 'Facturable',
275276
nonBillable: 'No facturable',
@@ -1631,6 +1632,7 @@ const translations: TranslationDeepObject<typeof en> = {
16311632
},
16321633
correctRateError: 'Corrige el error de la tasa y vuelve a intentarlo.',
16331634
AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Explicar<sparkles-icon/></a>`,
1635+
conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge asoció este gasto con <strong>${vendorName}</strong>`,
16341636
rulesModifiedFields: {
16351637
reimbursable: (value: boolean) => (value ? 'marcó el gasto como "reembolsable"' : 'marcó el gasto como "no reembolsable"'),
16361638
billable: (value: boolean) => (value ? 'marcó el gasto como "facturable"' : 'marcó el gasto como "no facturable"'),

src/languages/fr.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ const translations: TranslationDeepObject<typeof en> = {
314314
merchant: 'Commerçant',
315315
change: 'Modifier',
316316
category: 'Catégorie',
317+
vendor: 'Fournisseur',
317318
report: 'Note de frais',
318319
billable: 'Facturable',
319320
nonBillable: 'Non refacturable',
@@ -1671,6 +1672,7 @@ const translations: TranslationDeepObject<typeof en> = {
16711672
},
16721673
correctRateError: 'Corrigez l’erreur de taux et réessayez.',
16731674
AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Expliquer<sparkles-icon/></a>`,
1675+
conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge a associé cette dépense au fournisseur <strong>${vendorName}</strong>`,
16741676
duplicateNonDefaultWorkspacePerDiemError:
16751677
'Vous ne pouvez pas dupliquer les indemnités journalières entre plusieurs espaces de travail, car les taux peuvent différer d’un espace de travail à l’autre.',
16761678
rulesModifiedFields: {

src/languages/it.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ const translations: TranslationDeepObject<typeof en> = {
314314
merchant: 'Esercente',
315315
change: 'Modifica',
316316
category: 'Categoria',
317+
vendor: 'Fornitore',
317318
report: 'Report',
318319
billable: 'Fatturabile',
319320
nonBillable: 'Non fatturabile',
@@ -1664,6 +1665,7 @@ const translations: TranslationDeepObject<typeof en> = {
16641665
},
16651666
correctRateError: "Correggi l'errore di tariffa e riprova.",
16661667
AskToExplain: `. <a href="${CONST.CONCIERGE_EXPLAIN_LINK_PATH}">Spiega<sparkles-icon/></a>`,
1668+
conciergeAutoMatchedVendor: ({vendorName}: {vendorName: string}) => `Concierge ha associato questa spesa al fornitore <strong>${vendorName}</strong>`,
16671669
duplicateNonDefaultWorkspacePerDiemError: 'Non puoi duplicare le spese di diaria tra diversi spazi di lavoro perché le tariffe potrebbero essere diverse tra gli spazi di lavoro.',
16681670
rulesModifiedFields: {
16691671
reimbursable: (value: boolean) => (value ? 'ha contrassegnato la spesa come "rimborsabile"' : 'ha contrassegnato la spesa come "non rimborsabile"'),

0 commit comments

Comments
 (0)