@@ -8,7 +8,19 @@ import CONST from '@src/CONST';
88import ONYXKEYS from '@src/ONYXKEYS' ;
99import ROUTES from '@src/ROUTES' ;
1010import INPUT_IDS from '@src/types/form/NetSuiteCustomFieldForm' ;
11- import type { OnyxInputOrEntry , Policy , PolicyCategories , PolicyEmployeeList , PolicyTagLists , PolicyTags , Report , TaxRate , Transaction , TravelSettings } from '@src/types/onyx' ;
11+ import type {
12+ OnyxInputOrEntry ,
13+ PersonalDetailsList ,
14+ Policy ,
15+ PolicyCategories ,
16+ PolicyEmployeeList ,
17+ PolicyTagLists ,
18+ PolicyTags ,
19+ Report ,
20+ TaxRate ,
21+ Transaction ,
22+ TravelSettings ,
23+ } from '@src/types/onyx' ;
1224import type { ErrorFields , PendingAction , PendingFields } from '@src/types/onyx/OnyxCommon' ;
1325import type {
1426 ConnectionLastSync ,
@@ -508,6 +520,89 @@ function getIneligibleInvitees(employeeList?: PolicyEmployeeList): string[] {
508520 return memberEmailsToExclude ;
509521}
510522
523+ /**
524+ * Get Guide and Account Manager information including their emails/logins and exclusion record.
525+ * Used for filtering Guide/AM from contact lists while allowing manual entry.
526+ *
527+ * @param policy - The policy to get the assigned guide from
528+ * @param accountManagerAccountID - The account manager's account ID from the account object (string from ONYXKEYS.ACCOUNT)
529+ * @param personalDetails - Personal details collection to look up account manager login
530+ * @returns Object containing extracted emails/logins and exclusions record
531+ */
532+ function getGuideAndAccountManagerInfo (
533+ policy : OnyxEntry < Policy > ,
534+ accountManagerAccountID : string | undefined ,
535+ personalDetails : OnyxEntry < PersonalDetailsList > ,
536+ ) : {
537+ assignedGuideEmail : string | undefined ;
538+ accountManagerLogin : string | undefined ;
539+ exclusions : Record < string , boolean > ;
540+ } {
541+ const assignedGuideEmail = policy ?. assignedGuide ?. email ?. toLowerCase ( ) ;
542+ const accountManagerLogin = accountManagerAccountID ? personalDetails ?. [ Number ( accountManagerAccountID ) ] ?. login ?. toLowerCase ( ) : undefined ;
543+
544+ const exclusions : Record < string , boolean > = { } ;
545+ if ( assignedGuideEmail ) {
546+ exclusions [ assignedGuideEmail ] = true ;
547+ }
548+ if ( accountManagerLogin ) {
549+ exclusions [ accountManagerLogin ] = true ;
550+ }
551+
552+ return {
553+ assignedGuideEmail,
554+ accountManagerLogin,
555+ exclusions,
556+ } ;
557+ }
558+
559+ /**
560+ * Get soft exclusions (Guide/Account Manager) that should be hidden from auto-suggestions
561+ * but can still be manually entered by the user.
562+ *
563+ * @param policy - The policy to get the assigned guide from
564+ * @param accountManagerAccountID - The account manager's account ID from the account object (string from ONYXKEYS.ACCOUNT)
565+ * @param personalDetails - Personal details collection to look up account manager login
566+ * @returns Record mapping lowercase emails to true for Guide and Account Manager
567+ */
568+ function getSoftExclusionsForGuideAndAccountManager (
569+ policy : OnyxEntry < Policy > ,
570+ accountManagerAccountID : string | undefined ,
571+ personalDetails : OnyxEntry < PersonalDetailsList > ,
572+ ) : Record < string , boolean > {
573+ return getGuideAndAccountManagerInfo ( policy , accountManagerAccountID , personalDetails ) . exclusions ;
574+ }
575+
576+ /**
577+ * Filter out Guide and Account Manager from a list of items.
578+ * Used for filtering local data (e.g., policy.employeeList) that isn't filtered at the data layer.
579+ *
580+ * @param items - Array of items to filter (must have login or alternateText properties)
581+ * @param assignedGuideEmail - The assigned guide's email (should be lowercase)
582+ * @param accountManagerLogin - The account manager's login (should be lowercase)
583+ * @returns Filtered array with Guide and Account Manager removed
584+ */
585+ function filterGuideAndAccountManager < T extends { login ?: string | null ; alternateText ?: string | null } > (
586+ items : T [ ] ,
587+ assignedGuideEmail : string | undefined ,
588+ accountManagerLogin : string | undefined ,
589+ ) : T [ ] {
590+ return items . filter ( ( item ) => {
591+ const itemLogin = item . login ?. toLowerCase ( ) ;
592+ const itemAltText = item . alternateText ?. toLowerCase ( ) ;
593+
594+ if ( assignedGuideEmail && ( itemLogin === assignedGuideEmail || itemAltText === assignedGuideEmail ) ) {
595+ return false ;
596+ }
597+
598+ if ( accountManagerLogin && ( itemLogin === accountManagerLogin || itemAltText === accountManagerLogin ) ) {
599+ return false ;
600+ }
601+
602+ return true ;
603+ } ) ;
604+ }
605+
511606function getSortedTagKeys ( policyTagList : OnyxEntry < PolicyTagLists > ) : Array < keyof PolicyTagLists > {
512607 if ( isEmptyObject ( policyTagList ) ) {
513608 return [ ] ;
@@ -1796,6 +1891,9 @@ export {
17961891 getCountOfEnabledTagsOfList ,
17971892 getIneligibleInvitees ,
17981893 getMemberAccountIDsForWorkspace ,
1894+ getGuideAndAccountManagerInfo ,
1895+ getSoftExclusionsForGuideAndAccountManager ,
1896+ filterGuideAndAccountManager ,
17991897 getNumericValue ,
18001898 isMultiLevelTags ,
18011899 // This will be fixed as part of https://github.com/Expensify/App/issues/66397
0 commit comments