From e72e186f843ee165c16a241e771d271fcd52d24c Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Fri, 22 Mar 2024 16:54:10 +0300 Subject: [PATCH 1/4] order tags for multilevel tag violation --- src/libs/PolicyUtils.ts | 9 +++++++++ src/libs/Violations/ViolationsUtils.ts | 3 ++- tests/unit/ViolationUtilsTest.ts | 12 ++++++------ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 39e6c8932aad..f2a5f28d482d 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -198,6 +198,14 @@ function getTagLists(policyTagList: OnyxEntry): Array tagA.orderWeight - tagB.orderWeight); } +function getSortedTagKeys(policyTagList: OnyxEntry): Array { + if (isEmptyObject(policyTagList)) { + return []; + } + + return Object.keys(policyTagList).sort((key1, key2) => policyTagList[key1].orderWeight - policyTagList[key2].orderWeight); +} + /** * Gets a tag list of a policy by a tag index */ @@ -317,6 +325,7 @@ export { getIneligibleInvitees, getTagLists, getTagListName, + getSortedTagKeys, canEditTaxRate, getTagList, getCleanedTagName, diff --git a/src/libs/Violations/ViolationsUtils.ts b/src/libs/Violations/ViolationsUtils.ts index fe2e5af537a7..9296a81e3065 100644 --- a/src/libs/Violations/ViolationsUtils.ts +++ b/src/libs/Violations/ViolationsUtils.ts @@ -2,6 +2,7 @@ import reject from 'lodash/reject'; import Onyx from 'react-native-onyx'; import type {OnyxUpdate} from 'react-native-onyx'; import type {Phrase, PhraseParameters} from '@libs/Localize'; +import {getSortedTagKeys} from '@libs/PolicyUtils'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -55,7 +56,7 @@ function getTagViolationsForMultiLevelTags( policyRequiresTags: boolean, policyTagList: PolicyTagList, ): TransactionViolation[] { - const policyTagKeys = Object.keys(policyTagList); + const policyTagKeys = getSortedTagKeys(policyTagList); const selectedTags = updatedTransaction.tag?.split(CONST.COLON) ?? []; let newTransactionViolations = [...transactionViolations]; newTransactionViolations = newTransactionViolations.filter( diff --git a/tests/unit/ViolationUtilsTest.ts b/tests/unit/ViolationUtilsTest.ts index 354a90802077..30e6dc738d8b 100644 --- a/tests/unit/ViolationUtilsTest.ts +++ b/tests/unit/ViolationUtilsTest.ts @@ -211,7 +211,7 @@ describe('getViolationsOnyxData', () => { }, }, required: true, - orderWeight: 1, + orderWeight: 2, }, Region: { name: 'Region', @@ -222,7 +222,7 @@ describe('getViolationsOnyxData', () => { }, }, required: true, - orderWeight: 2, + orderWeight: 1, }, Project: { name: 'Project', @@ -251,25 +251,25 @@ describe('getViolationsOnyxData', () => { expect(result.value).toEqual([someTagLevelsRequiredViolation]); // Test case where transaction has 1 tag - transaction.tag = 'Accounting'; + transaction.tag = 'Africa'; someTagLevelsRequiredViolation.data = {errorIndexes: [1, 2]}; result = ViolationsUtils.getViolationsOnyxData(transaction, transactionViolations, policyRequiresTags, policyTags, policyRequiresCategories, policyCategories); expect(result.value).toEqual([someTagLevelsRequiredViolation]); // Test case where transaction has 2 tags - transaction.tag = 'Accounting::Project1'; + transaction.tag = 'Africa::Project1'; someTagLevelsRequiredViolation.data = {errorIndexes: [1]}; result = ViolationsUtils.getViolationsOnyxData(transaction, transactionViolations, policyRequiresTags, policyTags, policyRequiresCategories, policyCategories); expect(result.value).toEqual([someTagLevelsRequiredViolation]); // Test case where transaction has all tags - transaction.tag = 'Accounting:Africa:Project1'; + transaction.tag = 'Africa:Accounting:Project1'; result = ViolationsUtils.getViolationsOnyxData(transaction, transactionViolations, policyRequiresTags, policyTags, policyRequiresCategories, policyCategories); expect(result.value).toEqual([]); }); it('should return tagOutOfPolicy when a tag is not enabled in the policy but is set in the transaction', () => { policyTags.Department.tags.Accounting.enabled = false; - transaction.tag = 'Accounting:Africa:Project1'; + transaction.tag = 'Africa:Accounting:Project1'; const result = ViolationsUtils.getViolationsOnyxData(transaction, transactionViolations, policyRequiresTags, policyTags, policyRequiresCategories, policyCategories); const violation = {...tagOutOfPolicyViolation, data: {tagName: 'Department'}}; expect(result.value).toEqual([violation]); From 90126061d4ef1b32371d94bf1a426092ba02cf14 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Tue, 26 Mar 2024 12:07:29 +0300 Subject: [PATCH 2/4] used sorted keys on other places --- src/libs/PolicyUtils.ts | 18 +++++++++--------- src/libs/actions/Policy.ts | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 79ec5fe2b3a1..6f871bea7ab8 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -170,6 +170,14 @@ function getIneligibleInvitees(policyMembers: OnyxEntry, personal return memberEmailsToExclude; } +function getSortedTagKeys(policyTagList: OnyxEntry): Array { + if (isEmptyObject(policyTagList)) { + return []; + } + + return Object.keys(policyTagList).sort((key1, key2) => policyTagList[key1].orderWeight - policyTagList[key2].orderWeight); +} + /** * Gets a tag name of policy tags based on a tag index. */ @@ -178,7 +186,7 @@ function getTagListName(policyTagList: OnyxEntry, tagIndex: numbe return ''; } - const policyTagKeys = Object.keys(policyTagList ?? {}); + const policyTagKeys = getSortedTagKeys(policyTagList ?? {}); const policyTagKey = policyTagKeys[tagIndex] ?? ''; return policyTagList?.[policyTagKey]?.name ?? ''; @@ -197,14 +205,6 @@ function getTagLists(policyTagList: OnyxEntry): Array tagA.orderWeight - tagB.orderWeight); } -function getSortedTagKeys(policyTagList: OnyxEntry): Array { - if (isEmptyObject(policyTagList)) { - return []; - } - - return Object.keys(policyTagList).sort((key1, key2) => policyTagList[key1].orderWeight - policyTagList[key2].orderWeight); -} - /** * Gets a tag list of a policy by a tag index */ diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index 332c145c58c4..503e5a90cb60 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -2228,7 +2228,7 @@ function buildOptimisticPolicyRecentlyUsedTags(policyID?: string, transactionTag } const policyTags = allPolicyTags?.[`${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`] ?? {}; - const policyTagKeys = Object.keys(policyTags); + const policyTagKeys = PolicyUtils.getSortedTagKeys(policyTags); const policyRecentlyUsedTags = allRecentlyUsedTags?.[`${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${policyID}`] ?? {}; const newOptimisticPolicyRecentlyUsedTags: RecentlyUsedTags = {}; @@ -2238,7 +2238,7 @@ function buildOptimisticPolicyRecentlyUsedTags(policyID?: string, transactionTag } const tagListKey = policyTagKeys[index]; - newOptimisticPolicyRecentlyUsedTags[tagListKey] = [...new Set([...tag, ...(policyRecentlyUsedTags[tagListKey] ?? [])])]; + newOptimisticPolicyRecentlyUsedTags[tagListKey] = [...new Set([tag, ...(policyRecentlyUsedTags[tagListKey] ?? [])])]; }); return newOptimisticPolicyRecentlyUsedTags; From fb64691fed39070c4706e6c25d266822c5cb1e32 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Wed, 27 Mar 2024 12:29:28 +0300 Subject: [PATCH 3/4] used sorted keys for logic clarity --- src/libs/ModifiedExpenseMessage.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts index 3b3e24867a4f..0953c743f01c 100644 --- a/src/libs/ModifiedExpenseMessage.ts +++ b/src/libs/ModifiedExpenseMessage.ts @@ -193,8 +193,9 @@ function getForReportAction(reportID: string | undefined, reportAction: OnyxEntr const splittedTag = TransactionUtils.getTagArrayFromName(transactionTag); const splittedOldTag = TransactionUtils.getTagArrayFromName(oldTransactionTag); const localizedTagListName = Localize.translateLocal('common.tag'); + const sortedTagKeys = PolicyUtils.getSortedTagKeys(policyTags); - Object.keys(policyTags).forEach((policyTagKey, index) => { + sortedTagKeys.forEach((_, index) => { const policyTagListName = PolicyUtils.getTagListName(policyTags, index) || localizedTagListName; const newTag = splittedTag[index] ?? ''; From c6343c8e8325f2579bbcb860414f72d97e2f5cb4 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Thu, 28 Mar 2024 20:48:25 +0300 Subject: [PATCH 4/4] updated modifiedexpense logic --- src/libs/ModifiedExpenseMessage.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/ModifiedExpenseMessage.ts b/src/libs/ModifiedExpenseMessage.ts index 0953c743f01c..8f1cb89d695b 100644 --- a/src/libs/ModifiedExpenseMessage.ts +++ b/src/libs/ModifiedExpenseMessage.ts @@ -195,8 +195,8 @@ function getForReportAction(reportID: string | undefined, reportAction: OnyxEntr const localizedTagListName = Localize.translateLocal('common.tag'); const sortedTagKeys = PolicyUtils.getSortedTagKeys(policyTags); - sortedTagKeys.forEach((_, index) => { - const policyTagListName = PolicyUtils.getTagListName(policyTags, index) || localizedTagListName; + sortedTagKeys.forEach((policyTagKey, index) => { + const policyTagListName = policyTags[policyTagKey].name || localizedTagListName; const newTag = splittedTag[index] ?? ''; const oldTag = splittedOldTag[index] ?? '';