From 167efbae8ae855b197235ad4a773d6524d81bc4a Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Wed, 31 Jul 2024 12:35:17 +0200 Subject: [PATCH 01/15] add texts --- src/languages/en.ts | 8 ++++++++ src/languages/es.ts | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/src/languages/en.ts b/src/languages/en.ts index 67354e7ea30a..2036cdee530f 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -2758,6 +2758,10 @@ export default { title: 'Spend', subtitle: 'Enable optional functionality that helps you scale your team.', }, + earnSection: { + title: 'Earn', + subtitle: 'Enable optional functionality to streamline your revenue and get paid faster.', + }, organizeSection: { title: 'Organize', subtitle: 'Group and analyze spend, record every tax paid.', @@ -2791,6 +2795,10 @@ export default { title: 'Workflows', subtitle: 'Configure how spend is approved and paid.', }, + invoices: { + title: 'Invoices', + subtitle: 'Send and receive invoices.', + }, categories: { title: 'Categories', subtitle: 'Track and organize spend.', diff --git a/src/languages/es.ts b/src/languages/es.ts index 7a92d4d1217d..4056a9d97ef5 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -2810,6 +2810,10 @@ export default { title: 'Gasto', subtitle: 'Habilita otras funcionalidades que ayudan a aumentar tu equipo.', }, + earnSection: { + title: 'Gane', + subtitle: 'Habilite funciones opcionales para agilizar sus ingresos y cobrar con mayor rapidez.', + }, organizeSection: { title: 'Organizar', subtitle: 'Agrupa y analiza el gasto, registra cada impuesto pagado.', @@ -2843,6 +2847,10 @@ export default { title: 'Flujos de trabajo', subtitle: 'Configura cómo se aprueba y paga los gastos.', }, + invoices: { + title: 'Invoices', + subtitle: 'Send and receive invoices.', + }, categories: { title: 'Categorías', subtitle: 'Monitoriza y organiza los gastos.', From c1adffc1eba233cdccd17739192b97ad9a1bcbcf Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Wed, 31 Jul 2024 12:36:55 +0200 Subject: [PATCH 02/15] implement enablePolicyInvoices --- .../parameters/EnablePolicyInvoicesParams.ts | 6 +++ src/libs/API/parameters/index.ts | 1 + src/libs/API/types.ts | 2 + src/libs/actions/Policy/Policy.ts | 50 +++++++++++++++++++ src/types/onyx/Policy.ts | 3 ++ 5 files changed, 62 insertions(+) create mode 100644 src/libs/API/parameters/EnablePolicyInvoicesParams.ts diff --git a/src/libs/API/parameters/EnablePolicyInvoicesParams.ts b/src/libs/API/parameters/EnablePolicyInvoicesParams.ts new file mode 100644 index 000000000000..4e8e76622108 --- /dev/null +++ b/src/libs/API/parameters/EnablePolicyInvoicesParams.ts @@ -0,0 +1,6 @@ +type EnablePolicyInvoicesParams = { + policyID: string; + enabled: boolean; +}; + +export default EnablePolicyInvoicesParams; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index 6b95190cd1ed..de2b2ddd54ec 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -255,6 +255,7 @@ export type {default as ConnectPolicyToNetSuiteParams} from './ConnectPolicyToNe export type {default as CreateWorkspaceReportFieldParams} from './CreateWorkspaceReportFieldParams'; export type {default as UpdateWorkspaceReportFieldInitialValueParams} from './UpdateWorkspaceReportFieldInitialValueParams'; export type {default as EnableWorkspaceReportFieldListValueParams} from './EnableWorkspaceReportFieldListValueParams'; +export type {default as EnablePolicyInvoicesParams} from './EnablePolicyInvoicesParams'; export type {default as CreateWorkspaceReportFieldListValueParams} from './CreateWorkspaceReportFieldListValueParams'; export type {default as RemoveWorkspaceReportFieldListValueParams} from './RemoveWorkspaceReportFieldListValueParams'; export type {default as OpenPolicyExpensifyCardsPageParams} from './OpenPolicyExpensifyCardsPageParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index f15fba20bc98..4969f4e57e5c 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -196,6 +196,7 @@ const WRITE_COMMANDS = { ENABLE_POLICY_WORKFLOWS: 'EnablePolicyWorkflows', ENABLE_POLICY_REPORT_FIELDS: 'EnablePolicyReportFields', ENABLE_POLICY_EXPENSIFY_CARDS: 'EnablePolicyExpensifyCards', + ENABLE_POLICY_INVOICES: 'EnablePolicyInvoices', SET_POLICY_TAXES_CURRENCY_DEFAULT: 'SetPolicyCurrencyDefaultTax', SET_POLICY_TAXES_FOREIGN_CURRENCY_DEFAULT: 'SetPolicyForeignCurrencyDefaultTax', SET_POLICY_CUSTOM_TAX_NAME: 'SetPolicyCustomTaxName', @@ -514,6 +515,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.ENABLE_POLICY_WORKFLOWS]: Parameters.EnablePolicyWorkflowsParams; [WRITE_COMMANDS.ENABLE_POLICY_REPORT_FIELDS]: Parameters.EnablePolicyReportFieldsParams; [WRITE_COMMANDS.ENABLE_POLICY_EXPENSIFY_CARDS]: Parameters.EnablePolicyExpensifyCardsParams; + [WRITE_COMMANDS.ENABLE_POLICY_INVOICES]: Parameters.EnablePolicyInvoicesParams; [WRITE_COMMANDS.JOIN_POLICY_VIA_INVITE_LINK]: Parameters.JoinPolicyInviteLinkParams; [WRITE_COMMANDS.ACCEPT_JOIN_REQUEST]: Parameters.AcceptJoinRequestParams; [WRITE_COMMANDS.DECLINE_JOIN_REQUEST]: Parameters.DeclineJoinRequestParams; diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 1bce525e22bf..f5f4244b1f8e 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -14,6 +14,7 @@ import type { DeleteWorkspaceParams, EnablePolicyConnectionsParams, EnablePolicyExpensifyCardsParams, + EnablePolicyInvoicesParams, EnablePolicyReportFieldsParams, EnablePolicyTaxesParams, EnablePolicyWorkflowsParams, @@ -2916,6 +2917,54 @@ function enableDistanceRequestTax(policyID: string, customUnitName: string, cust API.write(WRITE_COMMANDS.ENABLE_DISTANCE_REQUEST_TAX, params, onyxData); } +function enablePolicyInvoices(policyID: string, enabled: boolean) { + const onyxData: OnyxData = { + optimisticData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + areInvoicesEnabled: enabled, + pendingFields: { + areInvoicesEnabled: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, + }, + }, + }, + ], + successData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + pendingFields: { + areInvoicesEnabled: null, + }, + }, + }, + ], + failureData: [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + areInvoicesEnabled: !enabled, + pendingFields: { + areInvoicesEnabled: null, + }, + }, + }, + ], + }; + + const parameters: EnablePolicyInvoicesParams = {policyID, enabled}; + + API.write(WRITE_COMMANDS.ENABLE_POLICY_INVOICES, parameters, onyxData); + + if (enabled && getIsNarrowLayout()) { + navigateWhenEnableFeature(policyID); + } +} + function openPolicyMoreFeaturesPage(policyID: string) { const params: OpenPolicyMoreFeaturesPageParams = {policyID}; @@ -3201,6 +3250,7 @@ export { enablePolicyTaxes, enablePolicyWorkflows, enableDistanceRequestTax, + enablePolicyInvoices, openPolicyMoreFeaturesPage, openPolicyProfilePage, openPolicyInitialPage, diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 5b781ed7c034..d0da37367ed4 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -1492,6 +1492,9 @@ type Policy = OnyxCommon.OnyxValueWithOfflineFeedback< /** Whether the Connections feature is enabled */ areConnectionsEnabled?: boolean; + /** Whether the Invoices features are enabled */ + areInvoicesEnabled?: boolean; + /** The verified bank account linked to the policy */ achAccount?: ACHAccount; From a911d3eecbb121d1734055176529f8a856506fa2 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Wed, 31 Jul 2024 12:37:11 +0200 Subject: [PATCH 03/15] extend canSendInvoice --- src/libs/PolicyUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index c74ef8075558..18df4695c496 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -501,7 +501,7 @@ function getActiveAdminWorkspaces(policies: OnyxCollection | null): Poli /** Whether the user can send invoice */ function canSendInvoice(policies: OnyxCollection | null): boolean { - return getActiveAdminWorkspaces(policies).length > 0; + return getActiveAdminWorkspaces(policies).some((policy) => policy?.areInvoicesEnabled); } function hasDependentTags(policy: OnyxEntry, policyTagList: OnyxEntry) { From 4283e240dccf26794aa8110e89dfc1bab2248838 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Wed, 31 Jul 2024 12:37:32 +0200 Subject: [PATCH 04/15] integrate invoice enabling in WorkspaceMoreFeaturesPage --- .../workspace/WorkspaceMoreFeaturesPage.tsx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx b/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx index e54914fc6817..645d3e2bf610 100644 --- a/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx +++ b/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx @@ -144,6 +144,19 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro }); } + const earnItems: Item[] = [ + { + icon: Illustrations.InvoiceBlue, + titleTranslationKey: 'workspace.moreFeatures.invoices.title', + subtitleTranslationKey: 'workspace.moreFeatures.invoices.subtitle', + isActive: policy?.areInvoicesEnabled ?? false, + pendingAction: policy?.pendingFields?.areInvoicesEnabled, + action: (isEnabled: boolean) => { + Policy.enablePolicyInvoices(policy?.id ?? '-1', isEnabled); + }, + }, + ]; + const organizeItems: Item[] = [ { icon: Illustrations.FolderOpen, @@ -247,6 +260,11 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro subtitleTranslationKey: 'workspace.moreFeatures.spendSection.subtitle', items: spendItems, }, + { + titleTranslationKey: 'workspace.moreFeatures.earnSection.title', + subtitleTranslationKey: 'workspace.moreFeatures.earnSection.subtitle', + items: earnItems, + }, { titleTranslationKey: 'workspace.moreFeatures.organizeSection.title', subtitleTranslationKey: 'workspace.moreFeatures.organizeSection.subtitle', From 64f6420d788b8f00a4c20804fcf5bef9e7e3095c Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Wed, 31 Jul 2024 12:56:20 +0200 Subject: [PATCH 05/15] restrict sending invoice when disabled --- src/libs/ReportUtils.ts | 2 +- .../sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 8c8629406155..f7a2d6257789 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -6041,7 +6041,7 @@ function getMoneyRequestOptions(report: OnyxEntry, policy: OnyxEntry { return isFocused || (topmostCentralPane?.name === SCREENS.SEARCH.CENTRAL_PANE && shouldUseNarrowLayout); }; -type PolicySelector = Pick; +type PolicySelector = Pick; type FloatingActionButtonAndPopoverOnyxProps = { /** The list of policies the user has access to. */ @@ -97,6 +97,7 @@ const policySelector = (policy: OnyxEntry): PolicySelector => pendingAction: policy.pendingAction, avatarURL: policy.avatarURL, name: policy.name, + areInvoicesEnabled: policy.areInvoicesEnabled, }) as PolicySelector; const getQuickActionIcon = (action: QuickActionName): React.FC => { From 1b2ff884c83aab0dc7c14798d3d9044460b97829 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Wed, 31 Jul 2024 13:11:03 +0200 Subject: [PATCH 06/15] check enabled workspaces --- src/pages/iou/request/step/IOURequestStepSendFrom.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepSendFrom.tsx b/src/pages/iou/request/step/IOURequestStepSendFrom.tsx index 74a1370fb00c..4ef14ab78144 100644 --- a/src/pages/iou/request/step/IOURequestStepSendFrom.tsx +++ b/src/pages/iou/request/step/IOURequestStepSendFrom.tsx @@ -41,9 +41,9 @@ function IOURequestStepSendFrom({route, transaction, allPolicies}: IOURequestSte const selectedWorkspace = useMemo(() => transaction?.participants?.find((participant) => participant.isSender), [transaction]); const workspaceOptions: WorkspaceListItem[] = useMemo(() => { - const activeAdminWorkspaces = PolicyUtils.getActiveAdminWorkspaces(allPolicies); + const availableWorkspaces = PolicyUtils.getActiveAdminWorkspaces(allPolicies).filter((policy) => policy?.areInvoicesEnabled); - return activeAdminWorkspaces + return availableWorkspaces .sort((policy1, policy2) => sortWorkspacesBySelected({policyID: policy1.id, name: policy1.name}, {policyID: policy2.id, name: policy2.name}, selectedWorkspace?.policyID)) .map((policy) => ({ text: policy.name, From be700df67628dea1541ab3b5287f9a8d8be62e13 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Thu, 1 Aug 2024 11:04:41 +0200 Subject: [PATCH 07/15] translate files --- src/languages/es.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/languages/es.ts b/src/languages/es.ts index 4056a9d97ef5..7bc85d0cc212 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -2812,7 +2812,7 @@ export default { }, earnSection: { title: 'Gane', - subtitle: 'Habilite funciones opcionales para agilizar sus ingresos y cobrar con mayor rapidez.', + subtitle: 'Habilita funciones opcionales para agilizar tus ingresos y recibir pagos más rápido.', }, organizeSection: { title: 'Organizar', @@ -2848,8 +2848,8 @@ export default { subtitle: 'Configura cómo se aprueba y paga los gastos.', }, invoices: { - title: 'Invoices', - subtitle: 'Send and receive invoices.', + title: 'Facturas', + subtitle: 'Enviar y recibir facturas.', }, categories: { title: 'Categorías', From 2e079b5d8e6e049c5d03d4b2861afbe66b24be98 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Thu, 1 Aug 2024 13:53:20 +0200 Subject: [PATCH 08/15] filter disabled workspaces for invoices --- src/libs/PolicyUtils.ts | 9 ++++++++- src/libs/actions/Policy/Policy.ts | 9 +++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 43f31d302d5a..83f6ccda8bfd 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -497,9 +497,15 @@ function getActiveAdminWorkspaces(policies: OnyxCollection | null): Poli return activePolicies.filter((policy) => shouldShowPolicy(policy, NetworkStore.isOffline()) && isPolicyAdmin(policy)); } +/** Whether the user can send invoice from the workspace */ +function canSendInvoiceFromWorkspace(policyID: string | undefined): boolean { + const policy = getPolicy(policyID); + return policy?.areInvoicesEnabled ?? false; +} + /** Whether the user can send invoice */ function canSendInvoice(policies: OnyxCollection | null): boolean { - return getActiveAdminWorkspaces(policies).some((policy) => policy?.areInvoicesEnabled); + return getActiveAdminWorkspaces(policies).some((policy) => canSendInvoiceFromWorkspace(policy.id)); } function hasDependentTags(policy: OnyxEntry, policyTagList: OnyxEntry) { @@ -924,6 +930,7 @@ export { isTaxTrackingEnabled, shouldShowPolicy, getActiveAdminWorkspaces, + canSendInvoiceFromWorkspace, canSendInvoice, hasDependentTags, getXeroTenants, diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index f5f4244b1f8e..47846384f9a6 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -198,10 +198,15 @@ function getPolicy(policyID: string | undefined): OnyxEntry { * Returns a primary policy for the user */ function getPrimaryPolicy(activePolicyID?: OnyxEntry): Policy | undefined { - const activeAdminWorkspaces = PolicyUtils.getActiveAdminWorkspaces(allPolicies); + if (!PolicyUtils.canSendInvoiceFromWorkspace(activePolicyID)) { + const activeAdminWorkspaces = PolicyUtils.getActiveAdminWorkspaces(allPolicies); + + return activeAdminWorkspaces.find((policy) => PolicyUtils.canSendInvoiceFromWorkspace(policy.id)); + } + const primaryPolicy: Policy | null | undefined = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${activePolicyID ?? '-1'}`]; - return primaryPolicy ?? activeAdminWorkspaces[0]; + return primaryPolicy; } /** From 73cf208867097ad31d34c12c826067553115efcc Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Thu, 1 Aug 2024 14:02:07 +0200 Subject: [PATCH 09/15] filter disabled invoices rooms --- src/libs/OptionsListUtils.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index a2936e398ddd..b6405eed7f74 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -2031,7 +2031,11 @@ function getOptions( reportOption.isPolicyExpenseChat && reportOption.ownerAccountID === currentUserAccountID && includeOwnedWorkspaceChats && !reportOption.isArchivedRoom; const shouldShowInvoiceRoom = - includeInvoiceRooms && ReportUtils.isInvoiceRoom(reportOption.item) && ReportUtils.isPolicyAdmin(reportOption.policyID ?? '', policies) && !reportOption.isArchivedRoom; + includeInvoiceRooms && + ReportUtils.isInvoiceRoom(reportOption.item) && + ReportUtils.isPolicyAdmin(reportOption.policyID ?? '', policies) && + !reportOption.isArchivedRoom && + PolicyUtils.canSendInvoiceFromWorkspace(reportOption.policyID); /** Exclude the report option if it doesn't meet any of the following conditions: From 49eb3f9332c40ba9319f6b776bb99220ca627898 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Thu, 1 Aug 2024 14:27:02 +0200 Subject: [PATCH 10/15] fix comment --- src/types/onyx/Policy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index d0da37367ed4..c5667e70ddd5 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -1492,7 +1492,7 @@ type Policy = OnyxCommon.OnyxValueWithOfflineFeedback< /** Whether the Connections feature is enabled */ areConnectionsEnabled?: boolean; - /** Whether the Invoices features are enabled */ + /** Whether the Invoices feature is enabled */ areInvoicesEnabled?: boolean; /** The verified bank account linked to the policy */ From fb8ea487a6976b42b738cc4338993af987b49647 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Fri, 2 Aug 2024 15:12:32 +0200 Subject: [PATCH 11/15] rename and improve getInvoicePrimaryWorkspace --- src/libs/actions/Policy/Policy.ts | 16 ++++++---------- .../request/MoneyRequestParticipantsSelector.tsx | 2 +- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 4996e0ede8ba..a64d3ff39886 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -203,16 +203,12 @@ function getPolicy(policyID: string | undefined): OnyxEntry { /** * Returns a primary policy for the user */ -function getPrimaryPolicy(activePolicyID?: OnyxEntry): Policy | undefined { - if (!PolicyUtils.canSendInvoiceFromWorkspace(activePolicyID)) { - const activeAdminWorkspaces = PolicyUtils.getActiveAdminWorkspaces(allPolicies); - - return activeAdminWorkspaces.find((policy) => PolicyUtils.canSendInvoiceFromWorkspace(policy.id)); +function getInvoicePrimaryWorkspace(activePolicyID?: OnyxEntry): Policy | undefined { + if (PolicyUtils.canSendInvoiceFromWorkspace(activePolicyID)) { + return allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${activePolicyID ?? '-1'}`]; } - - const primaryPolicy: Policy | null | undefined = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${activePolicyID ?? '-1'}`]; - - return primaryPolicy; + const activeAdminWorkspaces = PolicyUtils.getActiveAdminWorkspaces(allPolicies); + return activeAdminWorkspaces.find((policy) => PolicyUtils.canSendInvoiceFromWorkspace(policy.id)); } /** @@ -3277,7 +3273,7 @@ export { setPolicyCustomTaxName, clearPolicyErrorField, isCurrencySupportedForDirectReimbursement, - getPrimaryPolicy, + getInvoicePrimaryWorkspace, createDraftWorkspace, savePreferredExportMethod, buildPolicyData, diff --git a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx index 5f10b403f5e9..3f3981ee4262 100644 --- a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx +++ b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx @@ -248,7 +248,7 @@ function MoneyRequestParticipantsSelector({participants = CONST.EMPTY_ARRAY, onF ]; if (iouType === CONST.IOU.TYPE.INVOICE) { - const policyID = option.item && ReportUtils.isInvoiceRoom(option.item) ? option.policyID : Policy.getPrimaryPolicy(activePolicyID)?.id; + const policyID = option.item && ReportUtils.isInvoiceRoom(option.item) ? option.policyID : Policy.getInvoicePrimaryWorkspace(activePolicyID)?.id; newParticipants.push({ policyID, isSender: true, From f541571b44b0410daa54a5392741df2759feb9f5 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Fri, 2 Aug 2024 15:14:56 +0200 Subject: [PATCH 12/15] use canSendInvoiceFromWorkspace --- src/pages/iou/request/step/IOURequestStepSendFrom.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/iou/request/step/IOURequestStepSendFrom.tsx b/src/pages/iou/request/step/IOURequestStepSendFrom.tsx index 4ef14ab78144..9c7f792725a0 100644 --- a/src/pages/iou/request/step/IOURequestStepSendFrom.tsx +++ b/src/pages/iou/request/step/IOURequestStepSendFrom.tsx @@ -41,7 +41,7 @@ function IOURequestStepSendFrom({route, transaction, allPolicies}: IOURequestSte const selectedWorkspace = useMemo(() => transaction?.participants?.find((participant) => participant.isSender), [transaction]); const workspaceOptions: WorkspaceListItem[] = useMemo(() => { - const availableWorkspaces = PolicyUtils.getActiveAdminWorkspaces(allPolicies).filter((policy) => policy?.areInvoicesEnabled); + const availableWorkspaces = PolicyUtils.getActiveAdminWorkspaces(allPolicies).filter((policy) => PolicyUtils.canSendInvoiceFromWorkspace(policy.id)); return availableWorkspaces .sort((policy1, policy2) => sortWorkspacesBySelected({policyID: policy1.id, name: policy1.name}, {policyID: policy2.id, name: policy2.name}, selectedWorkspace?.policyID)) From 4acdd471e737c7fd885b4a4ef659bb3174249793 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Mon, 5 Aug 2024 15:25:47 +0200 Subject: [PATCH 13/15] comment some changes out --- src/libs/OptionsListUtils.ts | 8 +++----- src/libs/PolicyUtils.ts | 4 +++- src/libs/ReportUtils.ts | 4 +++- src/libs/actions/Policy/Policy.ts | 19 ++++++++++++++++--- .../MoneyRequestParticipantsSelector.tsx | 3 ++- .../request/step/IOURequestStepSendFrom.tsx | 4 +++- 6 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index b14cb19d0220..d39f9fd2a04b 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -2031,11 +2031,9 @@ function getOptions( reportOption.isPolicyExpenseChat && reportOption.ownerAccountID === currentUserAccountID && includeOwnedWorkspaceChats && !reportOption.isArchivedRoom; const shouldShowInvoiceRoom = - includeInvoiceRooms && - ReportUtils.isInvoiceRoom(reportOption.item) && - ReportUtils.isPolicyAdmin(reportOption.policyID ?? '', policies) && - !reportOption.isArchivedRoom && - PolicyUtils.canSendInvoiceFromWorkspace(reportOption.policyID); + includeInvoiceRooms && ReportUtils.isInvoiceRoom(reportOption.item) && ReportUtils.isPolicyAdmin(reportOption.policyID ?? '', policies) && !reportOption.isArchivedRoom; + // TODO: Uncomment the following line when the invoices screen is ready + // && PolicyUtils.canSendInvoiceFromWorkspace(reportOption.policyID); /** Exclude the report option if it doesn't meet any of the following conditions: diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 9a019b816482..d71f667c0064 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -506,7 +506,9 @@ function canSendInvoiceFromWorkspace(policyID: string | undefined): boolean { /** Whether the user can send invoice */ function canSendInvoice(policies: OnyxCollection | null): boolean { - return getActiveAdminWorkspaces(policies).some((policy) => canSendInvoiceFromWorkspace(policy.id)); + return getActiveAdminWorkspaces(policies).length > 0; + // TODO: Uncomment the following line when the invoices screen is ready + // return getActiveAdminWorkspaces(policies).some((policy) => canSendInvoiceFromWorkspace(policy.id)); } function hasDependentTags(policy: OnyxEntry, policyTagList: OnyxEntry) { diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 78fb53e55b77..f2d7bc84b204 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -6086,7 +6086,9 @@ function getMoneyRequestOptions(report: OnyxEntry, policy: OnyxEntry { /** * Returns a primary policy for the user */ +// TODO: Use getInvoicePrimaryWorkspace when the invoices screen is ready +function getPrimaryPolicy(activePolicyID?: OnyxEntry): Policy | undefined { + const activeAdminWorkspaces = PolicyUtils.getActiveAdminWorkspaces(allPolicies); + const primaryPolicy: Policy | null | undefined = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${activePolicyID ?? '-1'}`]; + + return primaryPolicy ?? activeAdminWorkspaces[0]; +} + +/** + * Returns a primary invoice workspace for the user + */ function getInvoicePrimaryWorkspace(activePolicyID?: OnyxEntry): Policy | undefined { if (PolicyUtils.canSendInvoiceFromWorkspace(activePolicyID)) { return allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${activePolicyID ?? '-1'}`]; @@ -2975,9 +2986,10 @@ function enablePolicyInvoices(policyID: string, enabled: boolean) { API.write(WRITE_COMMANDS.ENABLE_POLICY_INVOICES, parameters, onyxData); - if (enabled && getIsNarrowLayout()) { - navigateWhenEnableFeature(policyID); - } + // TODO: Uncomment the following line when the invoices screen is ready + // if (enabled && getIsNarrowLayout()) { + // navigateWhenEnableFeature(policyID); + // } } function openPolicyMoreFeaturesPage(policyID: string) { @@ -3281,6 +3293,7 @@ export { setPolicyCustomTaxName, clearPolicyErrorField, isCurrencySupportedForDirectReimbursement, + getPrimaryPolicy, getInvoicePrimaryWorkspace, createDraftWorkspace, savePreferredExportMethod, diff --git a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx index 3f3981ee4262..103b9a842c63 100644 --- a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx +++ b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx @@ -248,7 +248,8 @@ function MoneyRequestParticipantsSelector({participants = CONST.EMPTY_ARRAY, onF ]; if (iouType === CONST.IOU.TYPE.INVOICE) { - const policyID = option.item && ReportUtils.isInvoiceRoom(option.item) ? option.policyID : Policy.getInvoicePrimaryWorkspace(activePolicyID)?.id; + // TODO: Use getInvoicePrimaryWorkspace when the invoices screen is ready + const policyID = option.item && ReportUtils.isInvoiceRoom(option.item) ? option.policyID : Policy.getPrimaryPolicy(activePolicyID)?.id; newParticipants.push({ policyID, isSender: true, diff --git a/src/pages/iou/request/step/IOURequestStepSendFrom.tsx b/src/pages/iou/request/step/IOURequestStepSendFrom.tsx index 9c7f792725a0..7e46deba41cb 100644 --- a/src/pages/iou/request/step/IOURequestStepSendFrom.tsx +++ b/src/pages/iou/request/step/IOURequestStepSendFrom.tsx @@ -41,7 +41,9 @@ function IOURequestStepSendFrom({route, transaction, allPolicies}: IOURequestSte const selectedWorkspace = useMemo(() => transaction?.participants?.find((participant) => participant.isSender), [transaction]); const workspaceOptions: WorkspaceListItem[] = useMemo(() => { - const availableWorkspaces = PolicyUtils.getActiveAdminWorkspaces(allPolicies).filter((policy) => PolicyUtils.canSendInvoiceFromWorkspace(policy.id)); + const availableWorkspaces = PolicyUtils.getActiveAdminWorkspaces(allPolicies); + // TODO: Uncomment the following line when the invoices screen is ready + // .filter((policy) => PolicyUtils.canSendInvoiceFromWorkspace(policy.id)); return availableWorkspaces .sort((policy1, policy2) => sortWorkspacesBySelected({policyID: policy1.id, name: policy1.name}, {policyID: policy2.id, name: policy2.name}, selectedWorkspace?.policyID)) From c79964d52b02019dcb149799ee44047007de03a1 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Mon, 5 Aug 2024 15:39:42 +0200 Subject: [PATCH 14/15] link issue to todos --- src/libs/OptionsListUtils.ts | 2 +- src/libs/PolicyUtils.ts | 2 +- src/libs/ReportUtils.ts | 2 +- src/libs/actions/Policy/Policy.ts | 4 ++-- src/pages/iou/request/MoneyRequestParticipantsSelector.tsx | 2 +- src/pages/iou/request/step/IOURequestStepSendFrom.tsx | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index d39f9fd2a04b..32e23a817a9c 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -2032,7 +2032,7 @@ function getOptions( const shouldShowInvoiceRoom = includeInvoiceRooms && ReportUtils.isInvoiceRoom(reportOption.item) && ReportUtils.isPolicyAdmin(reportOption.policyID ?? '', policies) && !reportOption.isArchivedRoom; - // TODO: Uncomment the following line when the invoices screen is ready + // TODO: Uncomment the following line when the invoices screen is ready - https://github.com/Expensify/App/issues/45175. // && PolicyUtils.canSendInvoiceFromWorkspace(reportOption.policyID); /** diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index d71f667c0064..a43ea9723b38 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -507,7 +507,7 @@ function canSendInvoiceFromWorkspace(policyID: string | undefined): boolean { /** Whether the user can send invoice */ function canSendInvoice(policies: OnyxCollection | null): boolean { return getActiveAdminWorkspaces(policies).length > 0; - // TODO: Uncomment the following line when the invoices screen is ready + // TODO: Uncomment the following line when the invoices screen is ready - https://github.com/Expensify/App/issues/45175. // return getActiveAdminWorkspaces(policies).some((policy) => canSendInvoiceFromWorkspace(policy.id)); } diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index f2d7bc84b204..b05b615156ee 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -6086,7 +6086,7 @@ function getMoneyRequestOptions(report: OnyxEntry, policy: OnyxEntry { /** * Returns a primary policy for the user */ -// TODO: Use getInvoicePrimaryWorkspace when the invoices screen is ready +// TODO: Use getInvoicePrimaryWorkspace when the invoices screen is ready - https://github.com/Expensify/App/issues/45175. function getPrimaryPolicy(activePolicyID?: OnyxEntry): Policy | undefined { const activeAdminWorkspaces = PolicyUtils.getActiveAdminWorkspaces(allPolicies); const primaryPolicy: Policy | null | undefined = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${activePolicyID ?? '-1'}`]; @@ -2986,7 +2986,7 @@ function enablePolicyInvoices(policyID: string, enabled: boolean) { API.write(WRITE_COMMANDS.ENABLE_POLICY_INVOICES, parameters, onyxData); - // TODO: Uncomment the following line when the invoices screen is ready + // TODO: Uncomment the following line when the invoices screen is ready - https://github.com/Expensify/App/issues/45175. // if (enabled && getIsNarrowLayout()) { // navigateWhenEnableFeature(policyID); // } diff --git a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx index 103b9a842c63..cf47869e0052 100644 --- a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx +++ b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx @@ -248,7 +248,7 @@ function MoneyRequestParticipantsSelector({participants = CONST.EMPTY_ARRAY, onF ]; if (iouType === CONST.IOU.TYPE.INVOICE) { - // TODO: Use getInvoicePrimaryWorkspace when the invoices screen is ready + // TODO: Use getInvoicePrimaryWorkspace when the invoices screen is ready - https://github.com/Expensify/App/issues/45175. const policyID = option.item && ReportUtils.isInvoiceRoom(option.item) ? option.policyID : Policy.getPrimaryPolicy(activePolicyID)?.id; newParticipants.push({ policyID, diff --git a/src/pages/iou/request/step/IOURequestStepSendFrom.tsx b/src/pages/iou/request/step/IOURequestStepSendFrom.tsx index 7e46deba41cb..4c22b7f37e33 100644 --- a/src/pages/iou/request/step/IOURequestStepSendFrom.tsx +++ b/src/pages/iou/request/step/IOURequestStepSendFrom.tsx @@ -42,7 +42,7 @@ function IOURequestStepSendFrom({route, transaction, allPolicies}: IOURequestSte const workspaceOptions: WorkspaceListItem[] = useMemo(() => { const availableWorkspaces = PolicyUtils.getActiveAdminWorkspaces(allPolicies); - // TODO: Uncomment the following line when the invoices screen is ready + // TODO: Uncomment the following line when the invoices screen is ready - https://github.com/Expensify/App/issues/45175. // .filter((policy) => PolicyUtils.canSendInvoiceFromWorkspace(policy.id)); return availableWorkspaces From 5bdf6172bf0961f96d05faec2c4ba1403a3875c4 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Tue, 6 Aug 2024 12:36:44 +0200 Subject: [PATCH 15/15] rename invoicing --- src/libs/API/parameters/EnablePolicyInvoicesParams.ts | 6 ------ src/libs/API/parameters/EnablePolicyInvoicingParams.ts | 6 ++++++ src/libs/API/parameters/index.ts | 2 +- src/libs/API/types.ts | 4 ++-- src/libs/actions/Policy/Policy.ts | 10 +++++----- src/pages/workspace/WorkspaceMoreFeaturesPage.tsx | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) delete mode 100644 src/libs/API/parameters/EnablePolicyInvoicesParams.ts create mode 100644 src/libs/API/parameters/EnablePolicyInvoicingParams.ts diff --git a/src/libs/API/parameters/EnablePolicyInvoicesParams.ts b/src/libs/API/parameters/EnablePolicyInvoicesParams.ts deleted file mode 100644 index 4e8e76622108..000000000000 --- a/src/libs/API/parameters/EnablePolicyInvoicesParams.ts +++ /dev/null @@ -1,6 +0,0 @@ -type EnablePolicyInvoicesParams = { - policyID: string; - enabled: boolean; -}; - -export default EnablePolicyInvoicesParams; diff --git a/src/libs/API/parameters/EnablePolicyInvoicingParams.ts b/src/libs/API/parameters/EnablePolicyInvoicingParams.ts new file mode 100644 index 000000000000..c17268db84e7 --- /dev/null +++ b/src/libs/API/parameters/EnablePolicyInvoicingParams.ts @@ -0,0 +1,6 @@ +type EnablePolicyInvoicingParams = { + policyID: string; + enabled: boolean; +}; + +export default EnablePolicyInvoicingParams; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index de2b2ddd54ec..c89bf660fcd4 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -255,7 +255,7 @@ export type {default as ConnectPolicyToNetSuiteParams} from './ConnectPolicyToNe export type {default as CreateWorkspaceReportFieldParams} from './CreateWorkspaceReportFieldParams'; export type {default as UpdateWorkspaceReportFieldInitialValueParams} from './UpdateWorkspaceReportFieldInitialValueParams'; export type {default as EnableWorkspaceReportFieldListValueParams} from './EnableWorkspaceReportFieldListValueParams'; -export type {default as EnablePolicyInvoicesParams} from './EnablePolicyInvoicesParams'; +export type {default as EnablePolicyInvoicingParams} from './EnablePolicyInvoicingParams'; export type {default as CreateWorkspaceReportFieldListValueParams} from './CreateWorkspaceReportFieldListValueParams'; export type {default as RemoveWorkspaceReportFieldListValueParams} from './RemoveWorkspaceReportFieldListValueParams'; export type {default as OpenPolicyExpensifyCardsPageParams} from './OpenPolicyExpensifyCardsPageParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 2735e83650fa..57350bf6de13 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -197,7 +197,7 @@ const WRITE_COMMANDS = { ENABLE_POLICY_WORKFLOWS: 'EnablePolicyWorkflows', ENABLE_POLICY_REPORT_FIELDS: 'EnablePolicyReportFields', ENABLE_POLICY_EXPENSIFY_CARDS: 'EnablePolicyExpensifyCards', - ENABLE_POLICY_INVOICES: 'EnablePolicyInvoices', + ENABLE_POLICY_INVOICING: 'EnablePolicyInvoicing', SET_POLICY_TAXES_CURRENCY_DEFAULT: 'SetPolicyCurrencyDefaultTax', SET_POLICY_TAXES_FOREIGN_CURRENCY_DEFAULT: 'SetPolicyForeignCurrencyDefaultTax', SET_POLICY_CUSTOM_TAX_NAME: 'SetPolicyCustomTaxName', @@ -518,7 +518,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.ENABLE_POLICY_WORKFLOWS]: Parameters.EnablePolicyWorkflowsParams; [WRITE_COMMANDS.ENABLE_POLICY_REPORT_FIELDS]: Parameters.EnablePolicyReportFieldsParams; [WRITE_COMMANDS.ENABLE_POLICY_EXPENSIFY_CARDS]: Parameters.EnablePolicyExpensifyCardsParams; - [WRITE_COMMANDS.ENABLE_POLICY_INVOICES]: Parameters.EnablePolicyInvoicesParams; + [WRITE_COMMANDS.ENABLE_POLICY_INVOICING]: Parameters.EnablePolicyInvoicingParams; [WRITE_COMMANDS.JOIN_POLICY_VIA_INVITE_LINK]: Parameters.JoinPolicyInviteLinkParams; [WRITE_COMMANDS.ACCEPT_JOIN_REQUEST]: Parameters.AcceptJoinRequestParams; [WRITE_COMMANDS.DECLINE_JOIN_REQUEST]: Parameters.DeclineJoinRequestParams; diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 25915c09e13c..1aa87d053e66 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -14,7 +14,7 @@ import type { DeleteWorkspaceParams, EnablePolicyConnectionsParams, EnablePolicyExpensifyCardsParams, - EnablePolicyInvoicesParams, + EnablePolicyInvoicingParams, EnablePolicyReportFieldsParams, EnablePolicyTaxesParams, EnablePolicyWorkflowsParams, @@ -2943,7 +2943,7 @@ function enableDistanceRequestTax(policyID: string, customUnitName: string, cust API.write(WRITE_COMMANDS.ENABLE_DISTANCE_REQUEST_TAX, params, onyxData); } -function enablePolicyInvoices(policyID: string, enabled: boolean) { +function enablePolicyInvoicing(policyID: string, enabled: boolean) { const onyxData: OnyxData = { optimisticData: [ { @@ -2982,9 +2982,9 @@ function enablePolicyInvoices(policyID: string, enabled: boolean) { ], }; - const parameters: EnablePolicyInvoicesParams = {policyID, enabled}; + const parameters: EnablePolicyInvoicingParams = {policyID, enabled}; - API.write(WRITE_COMMANDS.ENABLE_POLICY_INVOICES, parameters, onyxData); + API.write(WRITE_COMMANDS.ENABLE_POLICY_INVOICING, parameters, onyxData); // TODO: Uncomment the following line when the invoices screen is ready - https://github.com/Expensify/App/issues/45175. // if (enabled && getIsNarrowLayout()) { @@ -3277,7 +3277,7 @@ export { enablePolicyTaxes, enablePolicyWorkflows, enableDistanceRequestTax, - enablePolicyInvoices, + enablePolicyInvoicing, openPolicyMoreFeaturesPage, openPolicyProfilePage, openPolicyInitialPage, diff --git a/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx b/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx index 645d3e2bf610..760155861f2a 100644 --- a/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx +++ b/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx @@ -152,7 +152,7 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro isActive: policy?.areInvoicesEnabled ?? false, pendingAction: policy?.pendingFields?.areInvoicesEnabled, action: (isEnabled: boolean) => { - Policy.enablePolicyInvoices(policy?.id ?? '-1', isEnabled); + Policy.enablePolicyInvoicing(policy?.id ?? '-1', isEnabled); }, }, ];