diff --git a/package.json b/package.json index 424c76cb0fc2..032b32914194 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "test:debug": "TZ=utc NODE_OPTIONS='--inspect-brk --experimental-vm-modules' jest --runInBand", "perf-test": "NODE_OPTIONS=--experimental-vm-modules npx reassure", "typecheck": "NODE_OPTIONS=--max_old_space_size=8192 tsc", - "lint": "NODE_OPTIONS=--max_old_space_size=8192 eslint . --max-warnings=111 --cache --cache-location=node_modules/.cache/eslint --cache-strategy content --concurrency=auto", + "lint": "NODE_OPTIONS=--max_old_space_size=8192 eslint . --max-warnings=110 --cache --cache-location=node_modules/.cache/eslint --cache-strategy content --concurrency=auto", "lint-changed": "NODE_OPTIONS=--max_old_space_size=8192 ./scripts/lintChanged.sh", "check-lazy-loading": "ts-node scripts/checkLazyLoading.ts", "lint-watch": "npx eslint-watch --watch --changed", diff --git a/src/libs/actions/IOU/SendInvoice.ts b/src/libs/actions/IOU/SendInvoice.ts index d42246c29e7e..dc3f9d285fef 100644 --- a/src/libs/actions/IOU/SendInvoice.ts +++ b/src/libs/actions/IOU/SendInvoice.ts @@ -34,15 +34,7 @@ import type {InvoiceReceiver, InvoiceReceiverType} from '@src/types/onyx/Report' import type {OnyxData} from '@src/types/onyx/Request'; import type {Receipt} from '@src/types/onyx/Transaction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import { - getAllPersonalDetails, - // eslint-disable-next-line @typescript-eslint/no-deprecated - getPolicyRecentlyUsedTagsData, - getReceiptError, - getSearchOnyxUpdate, - mergePolicyRecentlyUsedCategories, - mergePolicyRecentlyUsedCurrencies, -} from '.'; +import {getAllPersonalDetails, getReceiptError, getSearchOnyxUpdate, mergePolicyRecentlyUsedCategories, mergePolicyRecentlyUsedCurrencies} from '.'; import type {BasePolicyParams} from '.'; type SendInvoiceInformation = { @@ -72,6 +64,7 @@ type SendInvoiceOptions = { companyName?: string; companyWebsite?: string; policyRecentlyUsedCategories?: OnyxEntry; + policyRecentlyUsedTags?: OnyxEntry; }; type BuildOnyxDataForInvoiceParams = { @@ -536,6 +529,7 @@ function getSendInvoiceInformation({ companyName, companyWebsite, policyRecentlyUsedCategories, + policyRecentlyUsedTags, }: SendInvoiceOptions): SendInvoiceInformation { const {amount = 0, currency = '', created = '', merchant = '', category = '', tag = '', taxCode = '', taxAmount = 0, billable, comment, participants} = transaction ?? {}; const trimmedComment = (comment?.comment ?? '').trim(); @@ -592,9 +586,7 @@ function getSendInvoiceInformation({ const optimisticPolicyRecentlyUsedCategories = mergePolicyRecentlyUsedCategories(category, policyRecentlyUsedCategories); const optimisticPolicyRecentlyUsedTags = buildOptimisticPolicyRecentlyUsedTags({ policyTags: getPolicyTagsData(optimisticInvoiceReport.policyID), - // TODO: Replace getPolicyRecentlyUsedTagsData with useOnyx hook (https://github.com/Expensify/App/issues/71491) - // eslint-disable-next-line @typescript-eslint/no-deprecated - policyRecentlyUsedTags: getPolicyRecentlyUsedTagsData(optimisticInvoiceReport.policyID), + policyRecentlyUsedTags, transactionTags: tag, }); const optimisticRecentlyUsedCurrencies = mergePolicyRecentlyUsedCurrencies(currency, policyRecentlyUsedCurrencies); @@ -682,6 +674,7 @@ function sendInvoice({ companyName, companyWebsite, policyRecentlyUsedCategories, + policyRecentlyUsedTags, }: SendInvoiceOptions) { const parsedComment = getParsedComment(transaction?.comment?.comment?.trim() ?? ''); if (transaction?.comment) { @@ -713,6 +706,7 @@ function sendInvoice({ companyName, companyWebsite, policyRecentlyUsedCategories, + policyRecentlyUsedTags, }); const parameters: SendInvoiceParams = { diff --git a/src/libs/actions/IOU/index.ts b/src/libs/actions/IOU/index.ts index a83fc95c834f..6cc6cfdbe687 100644 --- a/src/libs/actions/IOU/index.ts +++ b/src/libs/actions/IOU/index.ts @@ -446,6 +446,7 @@ type PerDiemExpenseTransactionParams = Omit; policyTagList?: OnyxEntry; + policyRecentlyUsedTags?: OnyxEntry; policyCategories?: OnyxEntry; policyRecentlyUsedCategories?: OnyxEntry; }; @@ -620,6 +621,7 @@ type CreateSplitsAndOnyxDataParams = { existingSplitChatReportID?: string; transactionParams: CreateSplitsTransactionParams; policyRecentlyUsedCategories?: OnyxEntry; + policyRecentlyUsedTags: OnyxEntry; isASAPSubmitBetaEnabled: boolean; transactionViolations: OnyxCollection; quickAction: OnyxEntry; @@ -733,6 +735,7 @@ type StartSplitBilActionParams = { taxAmount: number; shouldPlaySound?: boolean; policyRecentlyUsedCategories?: OnyxEntry; + policyRecentlyUsedTags: OnyxEntry; quickAction: OnyxEntry; policyRecentlyUsedCurrencies: string[]; }; @@ -852,16 +855,6 @@ Onyx.connect({ }, }); -// TODO: remove `allRecentlyUsedTags` from this file (https://github.com/Expensify/App/issues/71491) -// `allRecentlyUsedTags` was moved here temporarily from `src/libs/actions/Policy/Tag.ts` during the `Deprecate Onyx.connect` refactor. -// All uses of this variable should be replaced with `useOnyx`. -let allRecentlyUsedTags: OnyxCollection = {}; -Onyx.connect({ - key: ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS, - waitForCollectionCallback: true, - callback: (val) => (allRecentlyUsedTags = val), -}); - let allReports: OnyxCollection; Onyx.connect({ key: ONYXKEYS.COLLECTION.REPORT, @@ -941,14 +934,6 @@ Onyx.connect({ callback: (val) => (recentWaypoints = val ?? []), }); -/** - * @deprecated This function uses Onyx.connect and should be replaced with useOnyx for reactive data access. - * All usages of this function should be replaced with useOnyx hook in React components. - */ -function getPolicyRecentlyUsedTagsData(policyID: string | undefined) { - return allRecentlyUsedTags?.[`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policyID}`] ?? {}; -} - /** * @private * After finishing the action in RHP from the Inbox tab, besides dismissing the modal, we should open the report. @@ -2927,7 +2912,7 @@ function getMoneyRequestInformation(moneyRequestInformation: MoneyRequestInforma policyRecentlyUsedCurrencies, } = moneyRequestInformation; const {payeeAccountID = userAccountID, payeeEmail = currentUserEmail, participant} = participantParams; - const {policy, policyCategories, policyTagList, policyRecentlyUsedCategories} = policyParams; + const {policy, policyCategories, policyTagList, policyRecentlyUsedCategories, policyRecentlyUsedTags} = policyParams; const { attendees, amount, @@ -3070,9 +3055,7 @@ function getMoneyRequestInformation(moneyRequestInformation: MoneyRequestInforma const optimisticPolicyRecentlyUsedCategories = mergePolicyRecentlyUsedCategories(category, policyRecentlyUsedCategories); const optimisticPolicyRecentlyUsedTags = buildOptimisticPolicyRecentlyUsedTags({ policyTags: getPolicyTagsData(iouReport.policyID), - // TODO: Replace getPolicyRecentlyUsedTagsData with useOnyx hook (https://github.com/Expensify/App/issues/71491) - // eslint-disable-next-line @typescript-eslint/no-deprecated - policyRecentlyUsedTags: getPolicyRecentlyUsedTagsData(iouReport.policyID), + policyRecentlyUsedTags, transactionTags: tag, }); const optimisticPolicyRecentlyUsedCurrencies = mergePolicyRecentlyUsedCurrencies(currency, policyRecentlyUsedCurrencies); @@ -3313,7 +3296,7 @@ function getPerDiemExpenseInformation(perDiemExpenseInformation: PerDiemExpenseI policyRecentlyUsedCurrencies, } = perDiemExpenseInformation; const {payeeAccountID = userAccountID, payeeEmail = currentUserEmail, participant} = participantParams; - const {policy, policyCategories, policyTagList, policyRecentlyUsedCategories} = policyParams; + const {policy, policyCategories, policyTagList, policyRecentlyUsedCategories, policyRecentlyUsedTags} = policyParams; const {destinations: recentlyUsedDestinations} = recentlyUsedParams; const {comment = '', currency, created, category, tag, customUnit, billable, attendees, reimbursable} = transactionParams; @@ -3406,9 +3389,7 @@ function getPerDiemExpenseInformation(perDiemExpenseInformation: PerDiemExpenseI const optimisticPolicyRecentlyUsedCategories = mergePolicyRecentlyUsedCategories(category, policyRecentlyUsedCategories); const optimisticPolicyRecentlyUsedTags = buildOptimisticPolicyRecentlyUsedTags({ policyTags: getPolicyTagsData(iouReport.policyID), - // TODO: Replace getPolicyRecentlyUsedTagsData with useOnyx hook (https://github.com/Expensify/App/issues/71491) - // eslint-disable-next-line @typescript-eslint/no-deprecated - policyRecentlyUsedTags: getPolicyRecentlyUsedTagsData(iouReport.policyID), + policyRecentlyUsedTags, transactionTags: tag, }); const optimisticPolicyRecentlyUsedCurrencies = mergePolicyRecentlyUsedCurrencies(currency, policyRecentlyUsedCurrencies); @@ -3871,6 +3852,7 @@ type GetUpdateMoneyRequestParamsType = { transactionChanges: TransactionChanges; policy: OnyxEntry; policyTagList: OnyxTypes.OnyxInputOrEntry; + policyRecentlyUsedTags?: OnyxEntry; policyCategories: OnyxTypes.OnyxInputOrEntry; policyRecentlyUsedCategories?: OnyxEntry; violations?: OnyxEntry; @@ -3891,6 +3873,7 @@ function getUpdateMoneyRequestParams(params: GetUpdateMoneyRequestParamsType): U transactionChanges, policy, policyTagList, + policyRecentlyUsedTags, policyCategories, policyRecentlyUsedCategories, violations, @@ -4193,9 +4176,7 @@ function getUpdateMoneyRequestParams(params: GetUpdateMoneyRequestParamsType): U if (hasModifiedTag) { const optimisticPolicyRecentlyUsedTags = buildOptimisticPolicyRecentlyUsedTags({ policyTags: getPolicyTagsData(iouReport?.policyID), - // TODO: Replace getPolicyRecentlyUsedTagsData with useOnyx hook (https://github.com/Expensify/App/issues/71491) - // eslint-disable-next-line @typescript-eslint/no-deprecated - policyRecentlyUsedTags: getPolicyRecentlyUsedTagsData(iouReport?.policyID), + policyRecentlyUsedTags, transactionTags: transactionChanges.tag, }); if (!isEmptyObject(optimisticPolicyRecentlyUsedTags)) { @@ -4801,19 +4782,34 @@ function updateMoneyRequestAttendees( API.write(WRITE_COMMANDS.UPDATE_MONEY_REQUEST_ATTENDEES, params, onyxData); } +type UpdateMoneyRequestTagParams = { + transactionID: string; + transactionThreadReportID: string | undefined; + tag: string; + policy: OnyxEntry; + policyTagList: OnyxEntry; + policyRecentlyUsedTags: OnyxEntry; + policyCategories: OnyxEntry; + currentUserAccountIDParam: number; + currentUserEmailParam: string; + isASAPSubmitBetaEnabled: boolean; + hash?: number; +}; + /** Updates the tag of an expense */ -function updateMoneyRequestTag( - transactionID: string, - transactionThreadReportID: string | undefined, - tag: string, - policy: OnyxEntry, - policyTagList: OnyxEntry, - policyCategories: OnyxEntry, - currentUserAccountIDParam: number, - currentUserEmailParam: string, - isASAPSubmitBetaEnabled: boolean, - hash?: number, -) { +function updateMoneyRequestTag({ + transactionID, + transactionThreadReportID, + tag, + policy, + policyTagList, + policyRecentlyUsedTags, + policyCategories, + currentUserAccountIDParam, + currentUserEmailParam, + isASAPSubmitBetaEnabled, + hash, +}: UpdateMoneyRequestTagParams) { const transactionChanges: TransactionChanges = { tag, }; @@ -4823,6 +4819,7 @@ function updateMoneyRequestTag( transactionChanges, policy, policyTagList, + policyRecentlyUsedTags, policyCategories, hash, currentUserAccountIDParam, @@ -6555,6 +6552,7 @@ function createSplitsAndOnyxData({ attendees, }, policyRecentlyUsedCategories, + policyRecentlyUsedTags, isASAPSubmitBetaEnabled, transactionViolations, quickAction, @@ -6932,9 +6930,7 @@ function createSplitsAndOnyxData({ const optimisticPolicyRecentlyUsedTags = isPolicyExpenseChat ? buildOptimisticPolicyRecentlyUsedTags({ policyTags: getPolicyTagsData(participant.policyID), - // TODO: Replace getPolicyRecentlyUsedTagsData with useOnyx hook (https://github.com/Expensify/App/issues/71491) - // eslint-disable-next-line @typescript-eslint/no-deprecated - policyRecentlyUsedTags: getPolicyRecentlyUsedTagsData(participant.policyID), + policyRecentlyUsedTags, transactionTags: tag, }) : {}; @@ -7046,6 +7042,7 @@ type SplitBillActionsParams = { taxAmount?: number; isRetry?: boolean; policyRecentlyUsedCategories?: OnyxEntry; + policyRecentlyUsedTags: OnyxEntry; isASAPSubmitBetaEnabled: boolean; transactionViolations: OnyxCollection; quickAction: OnyxEntry; @@ -7079,6 +7076,7 @@ function splitBill({ transactionViolations, quickAction, policyRecentlyUsedCurrencies, + policyRecentlyUsedTags, }: SplitBillActionsParams) { const parsedComment = getParsedComment(comment); const {splitData, splits, onyxData} = createSplitsAndOnyxData({ @@ -7102,6 +7100,7 @@ function splitBill({ taxAmount, }, policyRecentlyUsedCategories, + policyRecentlyUsedTags, isASAPSubmitBetaEnabled, transactionViolations, quickAction, @@ -7162,6 +7161,7 @@ function splitBillAndOpenReport({ taxAmount = 0, existingSplitChatReportID, policyRecentlyUsedCategories, + policyRecentlyUsedTags, isASAPSubmitBetaEnabled, transactionViolations, quickAction, @@ -7190,6 +7190,7 @@ function splitBillAndOpenReport({ taxAmount, }, policyRecentlyUsedCategories, + policyRecentlyUsedTags, transactionViolations, quickAction, policyRecentlyUsedCurrencies, @@ -7247,6 +7248,7 @@ function startSplitBill({ taxAmount = 0, shouldPlaySound = true, policyRecentlyUsedCategories, + policyRecentlyUsedTags, quickAction, policyRecentlyUsedCurrencies, }: StartSplitBilActionParams) { @@ -7419,6 +7421,7 @@ function startSplitBill({ taxAmount, quickAction, policyRecentlyUsedCurrencies, + policyRecentlyUsedTags, }; if (existingSplitChatReport) { @@ -7513,9 +7516,7 @@ function startSplitBill({ const optimisticPolicyRecentlyUsedCategories = mergePolicyRecentlyUsedCategories(category, policyRecentlyUsedCategories); const optimisticPolicyRecentlyUsedTags = buildOptimisticPolicyRecentlyUsedTags({ policyTags: getPolicyTagsData(participant.policyID), - // TODO: Replace getPolicyRecentlyUsedTagsData with useOnyx hook (https://github.com/Expensify/App/issues/71491) - // eslint-disable-next-line @typescript-eslint/no-deprecated - policyRecentlyUsedTags: getPolicyRecentlyUsedTagsData(participant.policyID), + policyRecentlyUsedTags, transactionTags: tag, }); const optimisticRecentlyUsedCurrencies = mergePolicyRecentlyUsedCurrencies(currency, policyRecentlyUsedCurrencies); @@ -7912,7 +7913,7 @@ function createDistanceRequest(distanceRequestInformation: CreateDistanceRequest quickAction, policyRecentlyUsedCurrencies, } = distanceRequestInformation; - const {policy, policyCategories, policyTagList, policyRecentlyUsedCategories} = policyParams; + const {policy, policyCategories, policyTagList, policyRecentlyUsedCategories, policyRecentlyUsedTags} = policyParams; const parsedComment = getParsedComment(transactionParams.comment); transactionParams.comment = parsedComment; const { @@ -7977,6 +7978,7 @@ function createDistanceRequest(distanceRequestInformation: CreateDistanceRequest attendees, }, policyRecentlyUsedCategories, + policyRecentlyUsedTags, isASAPSubmitBetaEnabled, transactionViolations, quickAction, @@ -8034,6 +8036,7 @@ function createDistanceRequest(distanceRequestInformation: CreateDistanceRequest policyCategories, policyTagList, policyRecentlyUsedCategories, + policyRecentlyUsedTags, }, transactionParams: { amount, @@ -14470,8 +14473,6 @@ export { getReportPreviewAction, mergePolicyRecentlyUsedCurrencies, mergePolicyRecentlyUsedCategories, - // eslint-disable-next-line @typescript-eslint/no-deprecated - getPolicyRecentlyUsedTagsData, getAllPersonalDetails, getReceiptError, getSearchOnyxUpdate, diff --git a/src/libs/actions/Policy/Tag.ts b/src/libs/actions/Policy/Tag.ts index bcb7edf7a2fb..636f9cff8ff4 100644 --- a/src/libs/actions/Policy/Tag.ts +++ b/src/libs/actions/Policy/Tag.ts @@ -65,7 +65,7 @@ function openPolicyTagsPage(policyID: string) { type BuildOptimisticPolicyRecentlyUsedTagsProps = { policyTags: PolicyTagLists; - policyRecentlyUsedTags: RecentlyUsedTags; + policyRecentlyUsedTags: OnyxEntry; transactionTags?: string; }; @@ -83,7 +83,7 @@ function buildOptimisticPolicyRecentlyUsedTags({policyTags, policyRecentlyUsedTa } const tagListKey = policyTagKeys.at(index) ?? ''; - newOptimisticPolicyRecentlyUsedTags[tagListKey] = [...new Set([tag, ...(policyRecentlyUsedTags[tagListKey] ?? [])])]; + newOptimisticPolicyRecentlyUsedTags[tagListKey] = [...new Set([tag, ...(policyRecentlyUsedTags?.[tagListKey] ?? [])])]; } return newOptimisticPolicyRecentlyUsedTags; diff --git a/src/pages/Share/SubmitDetailsPage.tsx b/src/pages/Share/SubmitDetailsPage.tsx index 450599223c67..4118b6c7a22b 100644 --- a/src/pages/Share/SubmitDetailsPage.tsx +++ b/src/pages/Share/SubmitDetailsPage.tsx @@ -59,6 +59,7 @@ function SubmitDetailsPage({ const [currentDate] = useOnyx(ONYXKEYS.CURRENT_DATE, {canBeMissing: true}); const [validFilesToUpload] = useOnyx(ONYXKEYS.VALIDATED_FILE_OBJECT, {canBeMissing: true}); const [policyRecentlyUsedCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES}${getIOURequestPolicyID(transaction, report)}`, {canBeMissing: true}); + const [policyRecentlyUsedTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${getIOURequestPolicyID(transaction, report)}`, {canBeMissing: true}); const [currentAttachment] = useOnyx(ONYXKEYS.SHARE_TEMP_FILE, {canBeMissing: true}); const shouldUsePreValidatedFile = shouldValidateFile(currentAttachment); const isLinkedTrackedExpenseReportArchived = useReportIsArchived(transaction?.linkedTrackedExpenseReportID); @@ -151,7 +152,7 @@ function SubmitDetailsPage({ requestMoney({ report, participantParams: {payeeEmail: currentUserPersonalDetails.login, payeeAccountID: currentUserPersonalDetails.accountID, participant}, - policyParams: {policy, policyTagList: policyTags, policyCategories, policyRecentlyUsedCategories}, + policyParams: {policy, policyTagList: policyTags, policyCategories, policyRecentlyUsedCategories, policyRecentlyUsedTags}, gpsPoint, action: CONST.IOU.TYPE.CREATE, transactionParams: { diff --git a/src/pages/iou/request/step/IOURequestStepCompanyInfo.tsx b/src/pages/iou/request/step/IOURequestStepCompanyInfo.tsx index 974446a6b186..9956c22cdd06 100644 --- a/src/pages/iou/request/step/IOURequestStepCompanyInfo.tsx +++ b/src/pages/iou/request/step/IOURequestStepCompanyInfo.tsx @@ -46,6 +46,7 @@ function IOURequestStepCompanyInfo({route, report, transaction}: IOURequestStepC const policy = usePolicy(policyID); const [policyRecentlyUsedCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES}${policyID}`, {canBeMissing: true}); const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`, {canBeMissing: true}); + const [policyRecentlyUsedTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policyID}`, {canBeMissing: true}); const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, {canBeMissing: true}); const [policyRecentlyUsedCurrencies] = useOnyx(ONYXKEYS.RECENTLY_USED_CURRENCIES, {canBeMissing: true}); @@ -87,6 +88,7 @@ function IOURequestStepCompanyInfo({route, report, transaction}: IOURequestStepC companyName: values.companyName, companyWebsite, policyRecentlyUsedCategories, + policyRecentlyUsedTags, }); }; diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 52ad09d843e5..e9ca980e28df 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -195,6 +195,7 @@ function IOURequestStepConfirmation({ const [policyCategoriesDraft] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES_DRAFT}${draftPolicyID}`, {canBeMissing: true}); const [policyRecentlyUsedCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES}${realPolicyID}`, {canBeMissing: true}); const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${realPolicyID}`, {canBeMissing: true}); + const [policyRecentlyUsedTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${realPolicyID}`, {canBeMissing: true}); const [policyRecentlyUsedCurrencies] = useOnyx(ONYXKEYS.RECENTLY_USED_CURRENCIES, {canBeMissing: true}); const [userLocation] = useOnyx(ONYXKEYS.USER_LOCATION, {canBeMissing: true}); @@ -576,6 +577,7 @@ function IOURequestStepConfirmation({ policyTagList: policyTags, policyCategories, policyRecentlyUsedCategories, + policyRecentlyUsedTags, }, gpsPoint, action, @@ -625,6 +627,7 @@ function IOURequestStepConfirmation({ currentUserPersonalDetails.accountID, policy, policyTags, + policyRecentlyUsedTags, policyCategories, policyRecentlyUsedCategories, action, @@ -665,6 +668,7 @@ function IOURequestStepConfirmation({ policyParams: { policy, policyTagList: policyTags, + policyRecentlyUsedTags, policyCategories, policyRecentlyUsedCategories: policyRecentlyUsedCategoriesParam, }, @@ -701,6 +705,7 @@ function IOURequestStepConfirmation({ isASAPSubmitBetaEnabled, hasViolations, policyRecentlyUsedCurrencies, + policyRecentlyUsedTags, ], ); @@ -801,6 +806,7 @@ function IOURequestStepConfirmation({ policyCategories, policyTagList: policyTags, policyRecentlyUsedCategories, + policyRecentlyUsedTags, }, transactionParams: { amount: transaction.amount, @@ -838,6 +844,7 @@ function IOURequestStepConfirmation({ policyCategories, policyTags, policyRecentlyUsedCategories, + policyRecentlyUsedTags, isManualDistanceRequest, transactionTaxCode, transactionTaxAmount, @@ -912,6 +919,7 @@ function IOURequestStepConfirmation({ taxAmount: transactionTaxAmount, shouldPlaySound: index === transactions.length - 1, policyRecentlyUsedCategories, + policyRecentlyUsedTags, quickAction, policyRecentlyUsedCurrencies: policyRecentlyUsedCurrencies ?? [], }); @@ -943,6 +951,7 @@ function IOURequestStepConfirmation({ taxCode: transactionTaxCode, taxAmount: transactionTaxAmount, policyRecentlyUsedCategories, + policyRecentlyUsedTags, isASAPSubmitBetaEnabled, transactionViolations, quickAction, @@ -973,6 +982,7 @@ function IOURequestStepConfirmation({ taxCode: transactionTaxCode, taxAmount: transactionTaxAmount, policyRecentlyUsedCategories, + policyRecentlyUsedTags, isASAPSubmitBetaEnabled, transactionViolations, quickAction, @@ -996,6 +1006,7 @@ function IOURequestStepConfirmation({ policyTagList: policyTags, policyCategories, policyRecentlyUsedCategories, + policyRecentlyUsedTags, }); return; } @@ -1100,6 +1111,7 @@ function IOURequestStepConfirmation({ transactionTaxCode, transactionTaxAmount, policyRecentlyUsedCategories, + policyRecentlyUsedTags, quickAction, isASAPSubmitBetaEnabled, transactionViolations, diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx index a18c1860af50..d67ef6bb4bab 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -447,6 +447,8 @@ function IOURequestStepScan({ taxAmount: transactionTaxAmount, quickAction, policyRecentlyUsedCurrencies: policyRecentlyUsedCurrencies ?? [], + // No need to update recently used tags because no tags are used when the confirmation step is skipped + policyRecentlyUsedTags: undefined, }); return; } diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.tsx index bcdef4b73763..ffc9eba87f2c 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.tsx @@ -503,6 +503,8 @@ function IOURequestStepScan({ taxAmount: transactionTaxAmount, quickAction, policyRecentlyUsedCurrencies: policyRecentlyUsedCurrencies ?? [], + // No need to update recently used tags because no tags are used when the confirmation step is skipped + policyRecentlyUsedTags: undefined, }); return; } diff --git a/src/pages/iou/request/step/IOURequestStepTag.tsx b/src/pages/iou/request/step/IOURequestStepTag.tsx index cd260d1fa086..910f5576eb96 100644 --- a/src/pages/iou/request/step/IOURequestStepTag.tsx +++ b/src/pages/iou/request/step/IOURequestStepTag.tsx @@ -51,6 +51,7 @@ function IOURequestStepTag({ const policy = isUnreportedExpense || isCreatingTrackExpense ? policyForMovingExpenses : reportPolicy; const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`, {canBeMissing: false}); const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, {canBeMissing: false}); + const [policyRecentlyUsedTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policyID}`, {canBeMissing: true}); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const currentUserAccountIDParam = currentUserPersonalDetails.accountID; const currentUserEmailParam = currentUserPersonalDetails.login ?? ''; @@ -132,18 +133,19 @@ function IOURequestStepTag({ } if (isEditing) { - updateMoneyRequestTag( + updateMoneyRequestTag({ transactionID, - report?.reportID, - updatedTag, + transactionThreadReportID: report?.reportID, + tag: updatedTag, policy, - policyTags, + policyTagList: policyTags, + policyRecentlyUsedTags, policyCategories, currentUserAccountIDParam, currentUserEmailParam, isASAPSubmitBetaEnabled, - currentSearchHash, - ); + hash: currentSearchHash, + }); navigateBack(); return; } diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index 6ab83b115ee0..5d312250b8f4 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -43,12 +43,14 @@ import { shouldOptimisticallyUpdateSearch, splitBill, startSplitBill, + submitPerDiemExpense, submitReport, trackExpense, unholdRequest, updateMoneyRequestAmountAndCurrency, updateMoneyRequestAttendees, updateMoneyRequestCategory, + updateMoneyRequestTag, updateSplitExpenseAmountField, updateSplitTransactionsFromSplitExpensesFlow, } from '@libs/actions/IOU'; @@ -85,7 +87,7 @@ import * as API from '@src/libs/API'; import DateUtils from '@src/libs/DateUtils'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import type {OriginalMessageIOU, PersonalDetailsList, Policy, Report, ReportNameValuePairs, SearchResults} from '@src/types/onyx'; +import type {OriginalMessageIOU, PersonalDetailsList, Policy, PolicyTagLists, RecentlyUsedTags, Report, ReportNameValuePairs, SearchResults} from '@src/types/onyx'; import type {Accountant, Attendee} from '@src/types/onyx/IOU'; import type {CurrentUserPersonalDetails} from '@src/types/onyx/PersonalDetails'; import type {Participant, ReportCollectionDataSet} from '@src/types/onyx/Report'; @@ -2193,6 +2195,70 @@ describe('actions/IOU', () => { expect(newNonReimbursableTotal).toBe(-100); }); + + it('should update policyRecentlyUsedTags when tag is provided', async () => { + // Given a policy recently used tags + const transactionTag = 'new tag'; + const policyID = 'A'; + const tagName = 'Tag'; + const expenseReport: Report = { + ...createRandomReport(0, undefined), + type: CONST.REPORT.TYPE.EXPENSE, + nonReimbursableTotal: 0, + total: 0, + ownerAccountID: RORY_ACCOUNT_ID, + currency: CONST.CURRENCY.USD, + policyID, + }; + const policyRecentlyUsedTags: OnyxEntry = { + [tagName]: ['old tag'], + }; + await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, { + [tagName]: {name: tagName}, + }); + await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policyID}`, policyRecentlyUsedTags); + + // When requesting money + requestMoney({ + report: expenseReport, + existingIOUReport: expenseReport, + participantParams: { + payeeEmail: RORY_EMAIL, + payeeAccountID: RORY_ACCOUNT_ID, + participant: {reportID: '1', isPolicyExpenseChat: true}, + }, + policyParams: {policyRecentlyUsedTags}, + transactionParams: { + amount: 100, + attendees: [], + currency: CONST.CURRENCY.USD, + created: '', + merchant: '', + comment: '', + tag: transactionTag, + }, + shouldGenerateTransactionThreadReport: true, + isASAPSubmitBetaEnabled: false, + transactionViolations: {}, + currentUserAccountIDParam: currentUserPersonalDetails.accountID, + currentUserEmailParam: currentUserPersonalDetails.login ?? '', + policyRecentlyUsedCurrencies: [], + }); + waitForBatchedUpdates(); + + // Then the transaction tag should be added to the recently used tags collection + const newPolicyRecentlyUsedTags: RecentlyUsedTags = await new Promise((resolve) => { + const connection = Onyx.connectWithoutView({ + key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policyID}`, + callback: (recentlyUsedTags) => { + resolve(recentlyUsedTags ?? {}); + Onyx.disconnect(connection); + }, + }); + }); + expect(newPolicyRecentlyUsedTags[tagName].length).toBe(2); + expect(newPolicyRecentlyUsedTags[tagName].at(0)).toBe(transactionTag); + }); }); describe('createDistanceRequest', () => { @@ -2315,7 +2381,126 @@ describe('actions/IOU', () => { const recentlyUsedCurrencies = await getOnyxValue(ONYXKEYS.RECENTLY_USED_CURRENCIES); expect(recentlyUsedCurrencies).toEqual([CONST.CURRENCY.GBP, ...initialCurrencies]); }); + + it('should update policyRecentlyUsedTags when tag is provided', async () => { + // Given a policy recently used tags + const transactionTag = 'new tag'; + const policyID = 'A'; + const tagName = 'Tag'; + const policyRecentlyUsedTags: OnyxEntry = { + [tagName]: ['old tag'], + }; + const iouReport = { + reportID: '3', + policyID, + type: CONST.REPORT.TYPE.EXPENSE, + ownerAccountID: currentUserPersonalDetails.accountID, + }; + await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`, iouReport); + await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`, {reportID: iouReport.reportID, policyID}); + await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, { + [tagName]: {name: tagName}, + }); + await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policyID}`, policyRecentlyUsedTags); + + // When creating a distance request + createDistanceRequest({ + report: iouReport, + participants: [{accountID: CARLOS_ACCOUNT_ID, login: CARLOS_EMAIL}], + currentUserLogin: RORY_EMAIL, + currentUserAccountID: RORY_ACCOUNT_ID, + transactionParams: { + amount: 1, + attendees: [], + currency: CONST.CURRENCY.GBP, + created: '', + merchant: '', + comment: '', + validWaypoints: {}, + tag: transactionTag, + }, + policyParams: {policyRecentlyUsedTags}, + isASAPSubmitBetaEnabled: false, + transactionViolations: {}, + quickAction: undefined, + policyRecentlyUsedCurrencies: [], + }); + waitForBatchedUpdates(); + + // Then the transaction tag should be added to the recently used tags collection + const newPolicyRecentlyUsedTags: RecentlyUsedTags = await new Promise((resolve) => { + const connection = Onyx.connectWithoutView({ + key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policyID}`, + callback: (recentlyUsedTags) => { + resolve(recentlyUsedTags ?? {}); + Onyx.disconnect(connection); + }, + }); + }); + expect(newPolicyRecentlyUsedTags[tagName].length).toBe(2); + expect(newPolicyRecentlyUsedTags[tagName].at(0)).toBe(transactionTag); + }); + + it('should update policyRecentlyUsedTags when splitting with tag is provided', async () => { + // Given a policy recently used tags + const transactionTag = 'new tag'; + const policyID = 'A'; + const tagName = 'Tag'; + const policyRecentlyUsedTags: OnyxEntry = { + [tagName]: ['old tag'], + }; + const policyExpenseChat = { + reportID: '2', + policyID, + isPolicyExpenseChat: true, + isOwnPolicyExpenseChat: true, + }; + await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${policyExpenseChat.reportID}`, policyExpenseChat); + await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, { + [tagName]: {name: tagName}, + }); + await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policyID}`, policyRecentlyUsedTags); + + // When creating a split distance request + createDistanceRequest({ + report: policyExpenseChat, + iouType: CONST.IOU.TYPE.SPLIT, + participants: [policyExpenseChat], + currentUserLogin: RORY_EMAIL, + currentUserAccountID: RORY_ACCOUNT_ID, + transactionParams: { + amount: 1, + attendees: [], + currency: CONST.CURRENCY.GBP, + created: '', + merchant: '', + comment: '', + validWaypoints: {}, + tag: transactionTag, + }, + policyParams: {policyRecentlyUsedTags}, + isASAPSubmitBetaEnabled: false, + transactionViolations: {}, + quickAction: undefined, + policyRecentlyUsedCurrencies: [], + }); + waitForBatchedUpdates(); + + // Then the transaction tag should be added to the recently used tags collection + const newPolicyRecentlyUsedTags: RecentlyUsedTags = await new Promise((resolve) => { + const connection = Onyx.connectWithoutView({ + key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policyID}`, + callback: (recentlyUsedTags) => { + resolve(recentlyUsedTags ?? {}); + Onyx.disconnect(connection); + }, + }); + }); + expect(newPolicyRecentlyUsedTags[tagName].length).toBe(2); + expect(newPolicyRecentlyUsedTags[tagName].at(0)).toBe(transactionTag); + }); }); + describe('split expense', () => { it('creates and updates new chats and IOUs as needed', () => { jest.setTimeout(10 * 1000); @@ -2487,6 +2672,7 @@ describe('actions/IOU', () => { transactionViolations: {}, quickAction: undefined, policyRecentlyUsedCurrencies: [], + policyRecentlyUsedTags: undefined, }, ); return waitForBatchedUpdates(); @@ -2823,6 +3009,7 @@ describe('actions/IOU', () => { transactionViolations: {}, quickAction: undefined, policyRecentlyUsedCurrencies: [], + policyRecentlyUsedTags: undefined, }); await waitForBatchedUpdates(); @@ -2869,6 +3056,7 @@ describe('actions/IOU', () => { transactionViolations: {}, quickAction: undefined, policyRecentlyUsedCurrencies: [], + policyRecentlyUsedTags: undefined, }); await waitForBatchedUpdates(); @@ -2889,6 +3077,7 @@ describe('actions/IOU', () => { transactionViolations: {}, quickAction: {action: CONST.QUICK_ACTIONS.SEND_MONEY, chatReportID: '456'}, policyRecentlyUsedCurrencies: [], + policyRecentlyUsedTags: undefined, }); await waitForBatchedUpdates(); @@ -2916,6 +3105,7 @@ describe('actions/IOU', () => { transactionViolations: {}, quickAction: undefined, policyRecentlyUsedCurrencies: initialCurrencies, + policyRecentlyUsedTags: undefined, }); await waitForBatchedUpdates(); @@ -2948,6 +3138,7 @@ describe('actions/IOU', () => { transactionViolations: {}, quickAction: undefined, policyRecentlyUsedCurrencies: [], + policyRecentlyUsedTags: undefined, }); await waitForBatchedUpdates(); @@ -2966,6 +3157,7 @@ describe('actions/IOU', () => { transactionViolations: {}, quickAction: undefined, policyRecentlyUsedCurrencies: [], + policyRecentlyUsedTags: undefined, }); await waitForBatchedUpdates(); @@ -3023,6 +3215,7 @@ describe('actions/IOU', () => { transactionViolations: {}, quickAction: undefined, policyRecentlyUsedCurrencies: [], + policyRecentlyUsedTags: undefined, }); await waitForBatchedUpdates(); @@ -3070,6 +3263,7 @@ describe('actions/IOU', () => { transactionViolations: {}, quickAction: undefined, policyRecentlyUsedCurrencies: [], + policyRecentlyUsedTags: undefined, }); await waitForBatchedUpdates(); @@ -3087,6 +3281,66 @@ describe('actions/IOU', () => { expect(report?.participants?.[RORY_ACCOUNT_ID].notificationPreference).toBe(CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS); }); + it('should update the policyRecentlyUsedTags when tag is provided', async () => { + // Given a policy recently used tags + const policyID = 'A'; + const transactionTag = 'new tag'; + const tagName = 'Tag'; + const policyRecentlyUsedTags: OnyxEntry = { + [tagName]: ['old tag'], + }; + + const policyExpenseChat = { + reportID: '2', + policyID, + isPolicyExpenseChat: true, + isOwnPolicyExpenseChat: true, + }; + + await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${policyExpenseChat.reportID}`, policyExpenseChat); + await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, { + [tagName]: {name: tagName}, + }); + await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policyID}`, policyRecentlyUsedTags); + + // When doing a split bill + splitBill({ + participants: [{isPolicyExpenseChat: true, policyID}], + existingSplitChatReportID: policyExpenseChat.reportID, + currentUserLogin: currentUserPersonalDetails.login ?? '', + currentUserAccountID: currentUserPersonalDetails.accountID, + amount: 1, + created: '', + comment: '', + merchant: '', + transactionViolations: undefined, + category: undefined, + tag: transactionTag, + currency: CONST.CURRENCY.USD, + taxCode: '', + taxAmount: 0, + isASAPSubmitBetaEnabled: false, + policyRecentlyUsedTags, + quickAction: {}, + policyRecentlyUsedCurrencies: [], + }); + + waitForBatchedUpdates(); + + // Then the transaction tag should be added to the recently used tags collection + const newPolicyRecentlyUsedTags: RecentlyUsedTags = await new Promise((resolve) => { + const connection = Onyx.connectWithoutView({ + key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policyID}`, + callback: (recentlyUsedTags) => { + resolve(recentlyUsedTags ?? {}); + Onyx.disconnect(connection); + }, + }); + }); + expect(newPolicyRecentlyUsedTags[tagName].length).toBe(2); + expect(newPolicyRecentlyUsedTags[tagName].at(0)).toBe(transactionTag); + }); + it('the description should not be parsed again after completing the scan split bill without changing the description', async () => { const reportID = '1'; await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, { @@ -3114,6 +3368,7 @@ describe('actions/IOU', () => { taxAmount: 0, quickAction: undefined, policyRecentlyUsedCurrencies: [], + policyRecentlyUsedTags: undefined, }); await waitForBatchedUpdates(); @@ -3147,6 +3402,55 @@ describe('actions/IOU', () => { }); }); + describe('startSplitBill', () => { + it('should update the policyRecentlyUsedTags when tag is provided', async () => { + // Given a policy recently used tags + const policyID = 'A'; + const transactionTag = 'new tag'; + const tagName = 'Tag'; + const policyRecentlyUsedTags: OnyxEntry = { + [tagName]: ['old tag'], + }; + + await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, { + [tagName]: {name: tagName}, + }); + await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policyID}`, policyRecentlyUsedTags); + + // When doing a split bill with a receipt + startSplitBill({ + participants: [{isPolicyExpenseChat: true, policyID}], + currentUserLogin: currentUserPersonalDetails.login ?? '', + currentUserAccountID: currentUserPersonalDetails.accountID, + comment: '', + receipt: {}, + category: undefined, + tag: transactionTag, + currency: CONST.CURRENCY.USD, + taxCode: '', + taxAmount: 0, + policyRecentlyUsedTags, + quickAction: {}, + policyRecentlyUsedCurrencies: [], + }); + + waitForBatchedUpdates(); + + // Then the transaction tag should be added to the recently used tags collection + const newPolicyRecentlyUsedTags: RecentlyUsedTags = await new Promise((resolve) => { + const connection = Onyx.connectWithoutView({ + key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policyID}`, + callback: (recentlyUsedTags) => { + resolve(recentlyUsedTags ?? {}); + Onyx.disconnect(connection); + }, + }); + }); + expect(newPolicyRecentlyUsedTags[tagName].length).toBe(2); + expect(newPolicyRecentlyUsedTags[tagName].at(0)).toBe(transactionTag); + }); + }); + describe('updateSplitTransactionsFromSplitExpensesFlow', () => { it('should delete the original transaction thread report', async () => { const expenseReport: Report = { @@ -10091,6 +10395,79 @@ describe('actions/IOU', () => { }); }); + describe('submitPerDiemExpense', () => { + it('should update policyRecentlyUsedTags when tag is provided', async () => { + // Given a transaction with a tag + const iouReportID = '2'; + const policyID = 'A'; + const transactionTag = 'new tag'; + const tagName = 'Tag'; + const policyRecentlyUsedTags: OnyxEntry = { + [tagName]: ['old tag'], + }; + + await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`, { + reportID: iouReportID, + policyID, + type: CONST.REPORT.TYPE.EXPENSE, + ownerAccountID: currentUserPersonalDetails.accountID, + }); + await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, { + [tagName]: {name: tagName}, + }); + await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policyID}`, policyRecentlyUsedTags); + + // When submitting a per diem expense + submitPerDiemExpense({ + currentUserAccountIDParam: currentUserPersonalDetails.accountID, + currentUserEmailParam: currentUserPersonalDetails.login ?? '', + hasViolations: false, + isASAPSubmitBetaEnabled: false, + participantParams: { + payeeEmail: currentUserPersonalDetails.login, + payeeAccountID: currentUserPersonalDetails.accountID, + participant: {}, + }, + report: { + reportID: '1', + iouReportID, + }, + transactionParams: { + created: DateUtils.getDBTime(), + currency: CONST.CURRENCY.USD, + tag: transactionTag, + customUnit: { + customUnitID: 'A', + name: CONST.CUSTOM_UNITS.NAME_PER_DIEM_INTERNATIONAL, + customUnitRateID: 'B', + subRates: [{id: '1', name: 'rate_a', quantity: 1, rate: 2}], + attributes: {dates: {end: '', start: ''}}, + }, + }, + policyRecentlyUsedCurrencies: [], + policyParams: { + policy: {...createRandomPolicy(1)}, + policyRecentlyUsedTags, + }, + }); + + waitForBatchedUpdates(); + + // Then the transaction tag should be added to the recently used tags collection + const newPolicyRecentlyUsedTags: RecentlyUsedTags = await new Promise((resolve) => { + const connection = Onyx.connectWithoutView({ + key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policyID}`, + callback: (recentlyUsedTags) => { + resolve(recentlyUsedTags ?? {}); + Onyx.disconnect(connection); + }, + }); + }); + expect(newPolicyRecentlyUsedTags[tagName].length).toBe(2); + expect(newPolicyRecentlyUsedTags[tagName].at(0)).toBe(transactionTag); + }); + }); + describe('updateMoneyRequestAttendees', () => { it('should update recent attendees', async () => { // Given a transaction @@ -10133,6 +10510,56 @@ describe('actions/IOU', () => { }); }); + describe('updateMoneyRequestTag', () => { + it('should update policyRecentlyUsedTags', async () => { + // Given a policy recently used tags + const policy = createRandomPolicy(1); + const tagName = 'Tag'; + const newTag = 'new tag'; + const policyTags: PolicyTagLists = { + [tagName]: {name: tagName, required: false, orderWeight: 0, tags: {A: {enabled: true, name: 'A'}}}, + }; + const policyRecentlyUsedTags: OnyxEntry = { + [tagName]: ['old tag'], + }; + const transactionThreadReportID = '2'; + const iouReportID = '3'; + await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policy.id}`, policyTags); + await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policy.id}`, policyRecentlyUsedTags); + await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`, {reportID: transactionThreadReportID, parentReportID: iouReportID}); + await Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`, {reportID: iouReportID, policyID: policy.id}); + + // When updating the expense tag + updateMoneyRequestTag({ + transactionID: '1', + transactionThreadReportID, + tag: newTag, + policy, + policyTagList: policyTags, + policyRecentlyUsedTags, + policyCategories: undefined, + currentUserAccountIDParam: currentUserPersonalDetails.accountID, + currentUserEmailParam: currentUserPersonalDetails.email ?? '', + isASAPSubmitBetaEnabled: false, + }); + + waitForBatchedUpdates(); + + // Then the transaction tag should be added to the recently used tags collection + const newPolicyRecentlyUsedTags: RecentlyUsedTags = await new Promise((resolve) => { + const connection = Onyx.connectWithoutView({ + key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policy.id}`, + callback: (recentlyUsedTags) => { + resolve(recentlyUsedTags ?? {}); + Onyx.disconnect(connection); + }, + }); + }); + expect(newPolicyRecentlyUsedTags[tagName].length).toBe(2); + expect(newPolicyRecentlyUsedTags[tagName].at(0)).toBe(newTag); + }); + }); + describe('rejectMoneyRequest', () => { const amount = 10000; const comment = 'This expense is rejected'; diff --git a/tests/actions/IOUTest/SendInvoiceTest.ts b/tests/actions/IOUTest/SendInvoiceTest.ts index d22a787e7ddb..42af684568b7 100644 --- a/tests/actions/IOUTest/SendInvoiceTest.ts +++ b/tests/actions/IOUTest/SendInvoiceTest.ts @@ -10,7 +10,7 @@ import IntlStore from '@src/languages/IntlStore'; import OnyxUpdateManager from '@src/libs/actions/OnyxUpdateManager'; import * as API from '@src/libs/API'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {PolicyTagLists, RecentlyUsedCategories, Report} from '@src/types/onyx'; +import type {PolicyTagLists, RecentlyUsedCategories, RecentlyUsedTags, Report} from '@src/types/onyx'; import type {Participant as IOUParticipant} from '@src/types/onyx/IOU'; import type {InvoiceReceiver} from '@src/types/onyx/Report'; import type Transaction from '@src/types/onyx/Transaction'; @@ -614,6 +614,47 @@ describe('actions/SendInvoice', () => { writeSpy.mockRestore(); }); + + it('should update policyRecentlyUsedTags when tag is provided', async () => { + // Given a transaction with a tag + const policyID = 'A'; + const transactionTag = 'new tag'; + const transaction: Transaction = { + ...createRandomTransaction(1), + tag: transactionTag, + participants: [{isSender: true, policyID}], + }; + const tagName = 'Tag'; + const policyRecentlyUsedTags: OnyxEntry = { + [tagName]: ['old tag'], + }; + await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, { + [tagName]: {name: tagName}, + }); + await Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policyID}`, policyRecentlyUsedTags); + + // When sending an invoice + sendInvoice({ + currentUserAccountID: 1, + transaction, + policyRecentlyUsedCurrencies: [], + policyRecentlyUsedTags, + }); + waitForBatchedUpdates(); + + // Then the transaction tag should be added to the recently used tags collection + const newPolicyRecentlyUsedTags: RecentlyUsedTags = await new Promise((resolve) => { + const connection = Onyx.connectWithoutView({ + key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policyID}`, + callback: (recentlyUsedTags) => { + resolve(recentlyUsedTags ?? {}); + Onyx.disconnect(connection); + }, + }); + }); + expect(newPolicyRecentlyUsedTags[tagName].length).toBe(2); + expect(newPolicyRecentlyUsedTags[tagName].at(0)).toBe(transactionTag); + }); }); describe('Invoice recipient change while offline', () => { const userAAccountID = 1;