From 16cae1b7a223551920651614bb558e506f52abed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Thu, 14 Mar 2024 14:37:08 +0100 Subject: [PATCH 01/30] handle errors --- .../WorkspaceAutoReportingFrequencyPage.tsx | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage.tsx b/src/pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage.tsx index cf66af726a72..5514d0c8a218 100644 --- a/src/pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage.tsx @@ -9,6 +9,7 @@ import ScreenWrapper from '@components/ScreenWrapper'; import RadioListItem from '@components/SelectionList/RadioListItem'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; +import * as ErrorUtils from '@libs/ErrorUtils'; import * as Localize from '@libs/Localize'; import Navigation from '@libs/Navigation/Navigation'; import * as PolicyUtils from '@libs/PolicyUtils'; @@ -80,7 +81,12 @@ function WorkspaceAutoReportingFrequencyPage({policy}: WorkspaceAutoReportingFre }; const monthlyFrequencyDetails = () => ( - + Policy.clearWorkspaceAutoReportingOffsetError(policy?.id ?? '')} + errorRowStyles={[styles.ml7]} + > - - item.text} - /> + Policy.clearWorkspaceAutoReportingFrequencyError(policy?.id ?? '')} + > + item.text} + /> + ); From cff3658b1bb64a03d6c877173c9ea32536d0f8fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Thu, 14 Mar 2024 14:37:26 +0100 Subject: [PATCH 02/30] add translations for workflows errors --- src/languages/en.ts | 10 ++++++++++ src/languages/es.ts | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/languages/en.ts b/src/languages/en.ts index 6ec5983583fc..e29ea4c0001c 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1072,9 +1072,19 @@ export default { }, }, }, + workflowsDelayedSubmissionPage: { + autoReportingErrorMessage: 'El parámetro de envío retrasado no pudo ser cambiado. Por favor, inténtelo de nuevo o contacte al soporte.', + autoReportingFrequencyErrorMessage: 'La frecuencia de envío no pudo ser cambiada. Por favor, inténtelo de nuevo o contacte al soporte.', + monthlyOffsetErrorMessage: 'La frecuencia mensual no pudo ser cambiada. Por favor, inténtelo de nuevo o contacte al soporte.', + }, + workflowsApprovalPage: { + genericErrorMessage: 'El aprobador no pudo ser cambiado. Por favor, inténtelo de nuevo o contacte al soporte.', + }, workflowsPayerPage: { title: 'Authorized payer', genericErrorMessage: 'The authorized payer could not be changed. Please try again.', + unavailableCurrencyErrorMessage: + 'Direct reimbursement is only available in USD, AUD, GBP, EUR and CAD. Currently this policy is set to a currency that is not eligible for direct reimbursement. Please change policy currency in order to enable Direct Reimbursement.', admins: 'Admins', }, reportFraudPage: { diff --git a/src/languages/es.ts b/src/languages/es.ts index c2eb6374affa..3c325a7ffa44 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1068,8 +1068,18 @@ export default { }, }, }, + workflowsDelayedSubmissionPage: { + autoReportingErrorMessage: 'El parámetro de envío retrasado no pudo ser cambiado. Por favor, inténtelo de nuevo o contacte al soporte.', + autoReportingFrequencyErrorMessage: 'La frecuencia de envío no pudo ser cambiada. Por favor, inténtelo de nuevo o contacte al soporte.', + monthlyOffsetErrorMessage: 'La frecuencia mensual no pudo ser cambiada. Por favor, inténtelo de nuevo o contacte al soporte.', + }, + workflowsApprovalPage: { + genericErrorMessage: 'El aprobador no pudo ser cambiado. Por favor, inténtelo de nuevo o contacte al soporte.', + }, workflowsPayerPage: { title: 'Pagador autorizado', + unavailableCurrencyErrorMessage: + 'El reembolso directo solo está disponible en USD, AUD, GBP, EUR y CAD. Actualmente, esta política está establecida en una moneda que no es elegible para el reembolso directo. Por favor, cambie la moneda de la política para poder habilitar el Reembolso Directo.', genericErrorMessage: 'El pagador autorizado no se pudo cambiar. Por favor, inténtalo mas tarde.', admins: 'Administradores', }, From 47c3c74fe0c4a37c2c3ad2bb4a0b67aa4b07c2d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Thu, 14 Mar 2024 14:37:42 +0100 Subject: [PATCH 03/30] handle workflows errors --- .../workspace/workflows/WorkspaceWorkflowsPage.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx index c6ace2b0856e..402ffb0263ec 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx @@ -78,6 +78,8 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses const hasVBA = state === BankAccount.STATE.OPEN; const bankDisplayName = bankName ? `${bankName} ${accountNumber ? `${accountNumber.slice(-5)}` : ''}` : ''; const hasReimburserEmailError = !!policy?.errorFields?.reimburserEmail; + const hasApprovalError = !!policy?.errorFields?.approvalMode; + const hasDelayedSubmissionError = !!policy?.errorFields?.autoReporting; return [ ...(canUseDelayedSubmission @@ -108,10 +110,13 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses shouldShowRightIcon wrapperStyle={containerStyle} hoverAndPressStyle={[styles.mr0, styles.br2]} + brickRoadIndicator={hasDelayedSubmissionError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} /> ), - isActive: (policy?.harvesting?.enabled && policy.autoReportingFrequency !== CONST.POLICY.AUTO_REPORTING_FREQUENCIES.INSTANT) ?? false, + isActive: (policy?.harvesting?.enabled && policy.autoReportingFrequency !== CONST.POLICY.AUTO_REPORTING_FREQUENCIES.INSTANT && !hasDelayedSubmissionError) ?? false, pendingAction: policy?.pendingFields?.isAutoApprovalEnabled, + errors: ErrorUtils.getLatestErrorField(policy ?? {}, 'autoReporting'), + onCloseError: () => Policy.clearWorkspaceAutoReportingError(policy?.id ?? ''), }, ] : []), @@ -132,10 +137,13 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses shouldShowRightIcon wrapperStyle={containerStyle} hoverAndPressStyle={[styles.mr0, styles.br2]} + brickRoadIndicator={hasApprovalError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} /> ), - isActive: policy?.isAutoApprovalEnabled ?? false, + isActive: (policy?.isAutoApprovalEnabled && !hasApprovalError) ?? false, pendingAction: policy?.pendingFields?.approvalMode, + errors: ErrorUtils.getLatestErrorField(policy ?? {}, 'approvalMode'), + onCloseError: () => Policy.clearWorkspaceApprovalError(policy?.id ?? ''), }, { icon: Illustrations.WalletAlt, From e515c8eb69f709911b538b54ee6eeb6572dbd69e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Thu, 14 Mar 2024 14:37:59 +0100 Subject: [PATCH 04/30] add errors for failure data --- src/libs/actions/Policy.ts | 40 +++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index 2adcfd29e00d..5ddd6784b92d 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -126,6 +126,14 @@ type WorkspaceMembersRoleData = { role: typeof CONST.POLICY.ROLE.ADMIN | typeof CONST.POLICY.ROLE.USER; }; +const CURRENCY_AU = 'AUD'; +const CURRENCY_CA = 'CAD'; +const CURRENCY_GB = 'GBP'; +const CURRENCY_US = 'USD'; +const CURRENCY_EUR = 'EUR'; + +const DIRECT_REIMBURSEMENT_CURRENCIES: string[] = [CURRENCY_AU, CURRENCY_CA, CURRENCY_EUR, CURRENCY_GB, CURRENCY_US]; + const allPolicies: OnyxCollection = {}; Onyx.connect({ key: ONYXKEYS.COLLECTION.POLICY, @@ -458,6 +466,7 @@ function setWorkspaceAutoReporting(policyID: string, enabled: boolean, frequency value: { autoReporting: !enabled, pendingFields: {isAutoApprovalEnabled: null, harvesting: null}, + errorFields: {autoReporting: ErrorUtils.getMicroSecondOnyxError('workflowsDelayedSubmissionPage.autoReportingErrorMessage')}, }, }, ]; @@ -495,6 +504,7 @@ function setWorkspaceAutoReportingFrequency(policyID: string, frequency: ValueOf key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { pendingFields: {autoReportingFrequency: null}, + errorFields: {autoReportingFrequency: ErrorUtils.getMicroSecondOnyxError('workflowsDelayedSubmissionPage.autoReportingFrequencyErrorMessage')}, }, }, ]; @@ -533,6 +543,7 @@ function setWorkspaceAutoReportingMonthlyOffset(policyID: string, autoReportingO key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { pendingFields: {autoReportingOffset: null}, + errorFields: {autoReportingOffset: ErrorUtils.getMicroSecondOnyxError('workflowsDelayedSubmissionPage.monthlyOffsetErrorMessage')}, }, }, ]; @@ -577,6 +588,7 @@ function setWorkspaceApprovalMode(policyID: string, approver: string, approvalMo key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { pendingFields: {approvalMode: null}, + errorFields: {approvalMode: ErrorUtils.getMicroSecondOnyxError('workflowsApprovalPage.genericErrorMessage')}, }, }, ]; @@ -640,12 +652,30 @@ function setWorkspacePayer(policyID: string, reimburserEmail: string, reimburser API.write(WRITE_COMMANDS.SET_WORKSPACE_PAYER, params, {optimisticData, failureData, successData}); } +function clearWorkspaceAutoReportingError(policyID: string) { + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {errorFields: {autoReporting: null}}); +} + +function clearWorkspaceAutoReportingFrequencyError(policyID: string) { + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {errorFields: {autoReportingFrequency: null}}); +} + +function clearWorkspaceAutoReportingOffsetError(policyID: string) { + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {errorFields: {autoReportingOffset: null}}); +} + +function clearWorkspaceApprovalError(policyID: string) { + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {errorFields: {approvalMode: null}}); +} + function clearWorkspacePayerError(policyID: string) { Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {errorFields: {reimburserEmail: null}}); } function setWorkspaceReimbursement(policyID: string, reimbursementChoice: ValueOf, reimburserAccountID: number, reimburserEmail: string) { const policy = ReportUtils.getPolicy(policyID); + // const policyCurrency = policy.outputCurrency; + const policyCurrency = 'xxx'; const optimisticData: OnyxUpdate[] = [ { @@ -671,6 +701,10 @@ function setWorkspaceReimbursement(policyID: string, reimbursementChoice: ValueO }, }, ]; + let onyxFailureMessage = ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage'); + if (!DIRECT_REIMBURSEMENT_CURRENCIES.includes(policyCurrency) && reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES) { + onyxFailureMessage = ErrorUtils.getMicroSecondOnyxError('workflowsPayerPage.unavailableCurrencyErrorMessage'); + } const failureData: OnyxUpdate[] = [ { @@ -680,7 +714,7 @@ function setWorkspaceReimbursement(policyID: string, reimbursementChoice: ValueO reimbursementChoice: policy.reimbursementChoice, reimburserAccountID: policy.reimburserAccountID, reimburserEmail: policy.reimburserEmail, - errorFields: {reimbursementChoice: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage')}, + errorFields: {reimbursementChoice: onyxFailureMessage}, pendingFields: {reimbursementChoice: null}, }, }, @@ -3591,4 +3625,8 @@ export { createPolicyTag, clearWorkspaceReimbursementErrors, deleteWorkspaceCategories, + clearWorkspaceApprovalError, + clearWorkspaceAutoReportingError, + clearWorkspaceAutoReportingFrequencyError, + clearWorkspaceAutoReportingOffsetError, }; From a280421e92b24f423ad438253ac450327b11a476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Thu, 14 Mar 2024 15:45:35 +0100 Subject: [PATCH 05/30] create method to check valid currency for reimbursement --- src/libs/actions/Policy.ts | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index 5ddd6784b92d..a35443b2c972 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -254,6 +254,14 @@ function updateLastAccessedWorkspace(policyID: OnyxEntry) { Onyx.set(ONYXKEYS.LAST_ACCESSED_WORKSPACE_POLICY_ID, policyID); } +function hasValidCurrencyForReimbursement(currency: string, reimbursementChoice: ValueOf) { + if (reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES) { + return DIRECT_REIMBURSEMENT_CURRENCIES.includes(currency); + } + + return true; +} + /** * Check if the user has any active free policies (aka workspaces) */ @@ -660,6 +668,10 @@ function clearWorkspaceAutoReportingFrequencyError(policyID: string) { Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {errorFields: {autoReportingFrequency: null}}); } +function clearWorkspaceGeneralSettingError(policyID: string) { + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {errorFields: {generalSettings: null}}); +} + function clearWorkspaceAutoReportingOffsetError(policyID: string) { Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {errorFields: {autoReportingOffset: null}}); } @@ -674,8 +686,6 @@ function clearWorkspacePayerError(policyID: string) { function setWorkspaceReimbursement(policyID: string, reimbursementChoice: ValueOf, reimburserAccountID: number, reimburserEmail: string) { const policy = ReportUtils.getPolicy(policyID); - // const policyCurrency = policy.outputCurrency; - const policyCurrency = 'xxx'; const optimisticData: OnyxUpdate[] = [ { @@ -702,7 +712,7 @@ function setWorkspaceReimbursement(policyID: string, reimbursementChoice: ValueO }, ]; let onyxFailureMessage = ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage'); - if (!DIRECT_REIMBURSEMENT_CURRENCIES.includes(policyCurrency) && reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES) { + if (!hasValidCurrencyForReimbursement(policy.outputCurrency, reimbursementChoice)) { onyxFailureMessage = ErrorUtils.getMicroSecondOnyxError('workflowsPayerPage.unavailableCurrencyErrorMessage'); } @@ -1376,13 +1386,17 @@ function updateGeneralSettings(policyID: string, name: string, currency: string) }, }, ]; + const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { errorFields: { - generalSettings: ErrorUtils.getMicroSecondOnyxError('workspace.editor.genericFailureMessage'), + generalSettings: + policy?.reimbursementChoice && !hasValidCurrencyForReimbursement(policy.outputCurrency, policy.reimbursementChoice) + ? ErrorUtils.getMicroSecondOnyxError('workflowsPayerPage.unavailableCurrencyErrorMessage') + : ErrorUtils.getMicroSecondOnyxError('workspace.editor.genericFailureMessage'), }, ...(distanceUnit?.customUnitID ? { @@ -3629,4 +3643,5 @@ export { clearWorkspaceAutoReportingError, clearWorkspaceAutoReportingFrequencyError, clearWorkspaceAutoReportingOffsetError, + clearWorkspaceGeneralSettingError, }; From ef1d1564a29c41fb6fc41c923fb4fa171b94777b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Thu, 14 Mar 2024 15:45:49 +0100 Subject: [PATCH 06/30] handle errors for workspace name and description --- src/pages/workspace/WorkspaceProfilePage.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/pages/workspace/WorkspaceProfilePage.tsx b/src/pages/workspace/WorkspaceProfilePage.tsx index 2df6dd0489f9..de1ae2d22473 100644 --- a/src/pages/workspace/WorkspaceProfilePage.tsx +++ b/src/pages/workspace/WorkspaceProfilePage.tsx @@ -18,6 +18,7 @@ import useLocalize from '@hooks/useLocalize'; import useThemeIllustrations from '@hooks/useThemeIllustrations'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; +import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as PolicyUtils from '@libs/PolicyUtils'; import * as ReportUtils from '@libs/ReportUtils'; @@ -156,7 +157,11 @@ function WorkspaceProfilePage({policy, currencyList = {}, route}: WorkSpaceProfi /> {(!StringUtils.isEmptyString(policy?.description ?? '') || !readOnly) && ( - + Policy.clearWorkspaceGeneralSettingError(policy?.id ?? '')} + > )} - + Policy.clearWorkspaceGeneralSettingError(policy?.id ?? '')} + errorRowStyles={[styles.mt2]} + > Date: Mon, 18 Mar 2024 14:53:58 +0100 Subject: [PATCH 07/30] make method more specific --- src/libs/actions/Policy.ts | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index a35443b2c972..94f0cefc8fde 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -254,14 +254,9 @@ function updateLastAccessedWorkspace(policyID: OnyxEntry) { Onyx.set(ONYXKEYS.LAST_ACCESSED_WORKSPACE_POLICY_ID, policyID); } -function hasValidCurrencyForReimbursement(currency: string, reimbursementChoice: ValueOf) { - if (reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES) { - return DIRECT_REIMBURSEMENT_CURRENCIES.includes(currency); - } - - return true; +function hasValidCurrencyForDirectReimbursement(currency: string) { + return DIRECT_REIMBURSEMENT_CURRENCIES.includes(currency); } - /** * Check if the user has any active free policies (aka workspaces) */ @@ -712,7 +707,7 @@ function setWorkspaceReimbursement(policyID: string, reimbursementChoice: ValueO }, ]; let onyxFailureMessage = ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage'); - if (!hasValidCurrencyForReimbursement(policy.outputCurrency, reimbursementChoice)) { + if (!hasValidCurrencyForDirectReimbursement(policy.outputCurrency)) { onyxFailureMessage = ErrorUtils.getMicroSecondOnyxError('workflowsPayerPage.unavailableCurrencyErrorMessage'); } @@ -1394,7 +1389,7 @@ function updateGeneralSettings(policyID: string, name: string, currency: string) value: { errorFields: { generalSettings: - policy?.reimbursementChoice && !hasValidCurrencyForReimbursement(policy.outputCurrency, policy.reimbursementChoice) + policy?.reimbursementChoice && !hasValidCurrencyForDirectReimbursement(policy.outputCurrency) ? ErrorUtils.getMicroSecondOnyxError('workflowsPayerPage.unavailableCurrencyErrorMessage') : ErrorUtils.getMicroSecondOnyxError('workspace.editor.genericFailureMessage'), }, @@ -3644,4 +3639,5 @@ export { clearWorkspaceAutoReportingFrequencyError, clearWorkspaceAutoReportingOffsetError, clearWorkspaceGeneralSettingError, + hasValidCurrencyForDirectReimbursement, }; From a7d48f2d97486c240cae61c83aa88822c13ba3f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Mon, 18 Mar 2024 15:00:01 +0100 Subject: [PATCH 08/30] show currency modal switcher if vbba not set and fix default reimbursement choice --- .../workflows/WorkspaceWorkflowsPage.tsx | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx index 402ffb0263ec..6357a3910bd9 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx @@ -1,5 +1,5 @@ import type {StackScreenProps} from '@react-navigation/stack'; -import React, {useCallback, useEffect, useMemo} from 'react'; +import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {FlatList, View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; @@ -29,6 +29,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import type {Beta, ReimbursementAccount, Session} from '@src/types/onyx'; +import ConfirmModal from '@components/ConfirmModal'; import ToggleSettingOptionRow from './ToggleSettingsOptionRow'; import type {ToggleSettingOptionRowProps} from './ToggleSettingsOptionRow'; import {getAutoReportingFrequencyDisplayNames} from './WorkspaceAutoReportingFrequencyPage'; @@ -53,6 +54,7 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses const policyApproverName = useMemo(() => PersonalDetailsUtils.getPersonalDetailByEmail(policyApproverEmail ?? '')?.displayName ?? policyApproverEmail, [policyApproverEmail]); const containerStyle = useMemo(() => [styles.ph8, styles.mhn8, styles.ml11, styles.pv3, styles.pr0, styles.pl4, styles.mr0, styles.widthAuto, styles.mt4], [styles]); const canUseDelayedSubmission = Permissions.canUseWorkflowsDelayedSubmission(betas); + const [isCurrencyModalOpen, setIsCurrencyModalOpen] = useState(false); const displayNameForAuthorizedPayer = useMemo(() => { const personalDetails = PersonalDetailsUtils.getPersonalDetailsByIDs([policy?.reimburserAccountID ?? 0], session?.accountID ?? 0); @@ -66,6 +68,15 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses Policy.openPolicyWorkflowsPage(policy?.id ?? route.params.policyID); }; + const confirmCurrencyChangeAndHideModal = useCallback(() => { + if (!policy) { + return; + } + Policy.updateGeneralSettings(policy.id, policy.name, CONST.CURRENCY.USD); + setIsCurrencyModalOpen(false); + navigateToBankAccountRoute(route.params.policyID, ROUTES.WORKSPACE_WORKFLOWS.getRoute(route.params.policyID)); + }, [policy, route.params.policyID]); + useNetwork({onReconnect: fetchData}); useEffect(() => { @@ -150,8 +161,7 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses title: translate('workflowsPage.makeOrTrackPaymentsTitle'), subtitle: translate('workflowsPage.makeOrTrackPaymentsDescription'), onToggle: () => { - const isActive = policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES; - const newReimbursementChoice = isActive ? CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL : CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES; + const newReimbursementChoice = !hasVBA ? CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL : CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES; const newReimburserAccountID = // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing PersonalDetailsUtils.getPersonalDetailByEmail(policy?.reimburserEmail ?? '')?.accountID || policy?.reimburserAccountID || policy?.ownerAccountID; @@ -165,7 +175,13 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses descriptionTextStyle={styles.textNormalThemeText} title={hasVBA ? translate('common.bankAccount') : translate('workflowsPage.connectBankAccount')} description={state === BankAccount.STATE.OPEN ? bankDisplayName : undefined} - onPress={() => navigateToBankAccountRoute(route.params.policyID, ROUTES.WORKSPACE_WORKFLOWS.getRoute(route.params.policyID))} + onPress={() => { + if (!Policy.hasValidCurrencyForDirectReimbursement(policy?.outputCurrency ?? '')) { + setIsCurrencyModalOpen(true); + return; + } + navigateToBankAccountRoute(route.params.policyID, ROUTES.WORKSPACE_WORKFLOWS.getRoute(route.params.policyID)); + }} shouldShowRightIcon wrapperStyle={containerStyle} hoverAndPressStyle={[styles.mr0, styles.br2]} @@ -258,6 +274,16 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses renderItem={renderOptionItem} keyExtractor={(item: ToggleSettingOptionRowProps) => item.title} /> + setIsCurrencyModalOpen(false)} + prompt={translate('workspace.bankAccount.updateCurrencyPrompt')} + confirmText={translate('workspace.bankAccount.updateToUSD')} + cancelText={translate('common.cancel')} + danger + /> From b3d99395de04265c016b2cdc978eb105e6b0c8b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Mon, 18 Mar 2024 15:00:43 +0100 Subject: [PATCH 09/30] fix style --- src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx index 6357a3910bd9..4504db31343b 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx @@ -3,6 +3,7 @@ import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {FlatList, View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; +import ConfirmModal from '@components/ConfirmModal'; import * as Illustrations from '@components/Icon/Illustrations'; import MenuItem from '@components/MenuItem'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; @@ -29,7 +30,6 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import type {Beta, ReimbursementAccount, Session} from '@src/types/onyx'; -import ConfirmModal from '@components/ConfirmModal'; import ToggleSettingOptionRow from './ToggleSettingsOptionRow'; import type {ToggleSettingOptionRowProps} from './ToggleSettingsOptionRow'; import {getAutoReportingFrequencyDisplayNames} from './WorkspaceAutoReportingFrequencyPage'; From 20af98eeea35d5ed151785ec9c0fb6ca145cbc15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Mon, 18 Mar 2024 15:17:03 +0100 Subject: [PATCH 10/30] remove unneeded translation key --- src/languages/en.ts | 2 -- src/languages/es.ts | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index e29ea4c0001c..674299c91551 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1083,8 +1083,6 @@ export default { workflowsPayerPage: { title: 'Authorized payer', genericErrorMessage: 'The authorized payer could not be changed. Please try again.', - unavailableCurrencyErrorMessage: - 'Direct reimbursement is only available in USD, AUD, GBP, EUR and CAD. Currently this policy is set to a currency that is not eligible for direct reimbursement. Please change policy currency in order to enable Direct Reimbursement.', admins: 'Admins', }, reportFraudPage: { diff --git a/src/languages/es.ts b/src/languages/es.ts index 3c325a7ffa44..01806dc835b8 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -1078,8 +1078,6 @@ export default { }, workflowsPayerPage: { title: 'Pagador autorizado', - unavailableCurrencyErrorMessage: - 'El reembolso directo solo está disponible en USD, AUD, GBP, EUR y CAD. Actualmente, esta política está establecida en una moneda que no es elegible para el reembolso directo. Por favor, cambie la moneda de la política para poder habilitar el Reembolso Directo.', genericErrorMessage: 'El pagador autorizado no se pudo cambiar. Por favor, inténtalo mas tarde.', admins: 'Administradores', }, From be8fd34207b0994685d481e91b55799fb8cb9e67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Mon, 18 Mar 2024 15:17:48 +0100 Subject: [PATCH 11/30] remove old logic for edge case when default reimbursement choice was set to yes --- src/libs/actions/Policy.ts | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index 94f0cefc8fde..da8141f0d519 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -706,10 +706,6 @@ function setWorkspaceReimbursement(policyID: string, reimbursementChoice: ValueO }, }, ]; - let onyxFailureMessage = ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage'); - if (!hasValidCurrencyForDirectReimbursement(policy.outputCurrency)) { - onyxFailureMessage = ErrorUtils.getMicroSecondOnyxError('workflowsPayerPage.unavailableCurrencyErrorMessage'); - } const failureData: OnyxUpdate[] = [ { @@ -719,7 +715,7 @@ function setWorkspaceReimbursement(policyID: string, reimbursementChoice: ValueO reimbursementChoice: policy.reimbursementChoice, reimburserAccountID: policy.reimburserAccountID, reimburserEmail: policy.reimburserEmail, - errorFields: {reimbursementChoice: onyxFailureMessage}, + errorFields: {reimbursementChoice: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage')}, pendingFields: {reimbursementChoice: null}, }, }, @@ -1388,10 +1384,7 @@ function updateGeneralSettings(policyID: string, name: string, currency: string) key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { errorFields: { - generalSettings: - policy?.reimbursementChoice && !hasValidCurrencyForDirectReimbursement(policy.outputCurrency) - ? ErrorUtils.getMicroSecondOnyxError('workflowsPayerPage.unavailableCurrencyErrorMessage') - : ErrorUtils.getMicroSecondOnyxError('workspace.editor.genericFailureMessage'), + generalSettings: ErrorUtils.getMicroSecondOnyxError('workspace.editor.genericFailureMessage'), }, ...(distanceUnit?.customUnitID ? { From c1c65f69e775b45c50a0e962280255b1e1ee33bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Mon, 18 Mar 2024 15:24:34 +0100 Subject: [PATCH 12/30] fix typo --- src/languages/en.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index b664012af37b..4def1f7d7280 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -1073,12 +1073,12 @@ export default { }, }, workflowsDelayedSubmissionPage: { - autoReportingErrorMessage: 'El parámetro de envío retrasado no pudo ser cambiado. Por favor, inténtelo de nuevo o contacte al soporte.', - autoReportingFrequencyErrorMessage: 'La frecuencia de envío no pudo ser cambiada. Por favor, inténtelo de nuevo o contacte al soporte.', - monthlyOffsetErrorMessage: 'La frecuencia mensual no pudo ser cambiada. Por favor, inténtelo de nuevo o contacte al soporte.', + autoReportingErrorMessage: 'The delayed submission parameter could not be changed. Please try again or contact support.', + autoReportingFrequencyErrorMessage: 'The submission frequency could not be changed. Please try again or contact support.', + monthlyOffsetErrorMessage: 'The monthly frequency could not be changed. Please try again or contact support.', }, workflowsApprovalPage: { - genericErrorMessage: 'El aprobador no pudo ser cambiado. Por favor, inténtelo de nuevo o contacte al soporte.', + genericErrorMessage: 'The approver could not be changed. Please try again or contact support.', }, workflowsPayerPage: { title: 'Authorized payer', From f385e85a63d19c5015f0753b24d775a830f788fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Tue, 19 Mar 2024 09:11:35 +0100 Subject: [PATCH 13/30] add consts for policy collection fields --- src/CONST.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/CONST.ts b/src/CONST.ts index c3e61c0c75d8..f3a4edc9911a 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1456,6 +1456,16 @@ const CONST = { DISABLE: 'disable', ENABLE: 'enable', }, + COLLECTION_FIELDS: { + DESCRIPTION: 'description', + REIMBURSER_EMAIL: 'reimburserEmail', + REIMBURSEMENT_CHOICE: 'reimbursementChoice', + APPROVAL_MODE: 'approvalMode', + AUTOREPORTING: 'autoReporting', + AUTOREPORTING_FREQUENCY: 'autoReportingFrequency', + AUTOREPORTING_OFFSET: 'autoReportingOffset', + GENERAL_SETTINGS: 'generalSettings', + }, }, CUSTOM_UNITS: { From 7cc1c1add711f9e8ffdf58085d98e94addcfa3a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Tue, 19 Mar 2024 09:12:04 +0100 Subject: [PATCH 14/30] add generic method to clear policy error fields --- src/libs/actions/Policy.ts | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index d4606d8ca15a..73baf68f8c74 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -672,29 +672,9 @@ function setWorkspacePayer(policyID: string, reimburserEmail: string, reimburser API.write(WRITE_COMMANDS.SET_WORKSPACE_PAYER, params, {optimisticData, failureData, successData}); } -function clearWorkspaceAutoReportingError(policyID: string) { - Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {errorFields: {autoReporting: null}}); -} - -function clearWorkspaceAutoReportingFrequencyError(policyID: string) { - Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {errorFields: {autoReportingFrequency: null}}); -} - -function clearWorkspaceGeneralSettingError(policyID: string) { - Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {errorFields: {generalSettings: null}}); -} - -function clearWorkspaceAutoReportingOffsetError(policyID: string) { - Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {errorFields: {autoReportingOffset: null}}); -} - -function clearWorkspaceApprovalError(policyID: string) { - Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {errorFields: {approvalMode: null}}); -} - -function clearWorkspacePayerError(policyID: string) { - Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {errorFields: {reimburserEmail: null}}); -} +function clearPolicyErrorField(policyID: string, fieldName: string) { + Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {errorFields: {[fieldName]: null}}); +} function setWorkspaceReimbursement(policyID: string, reimbursementChoice: ValueOf, reimburserAccountID: number, reimburserEmail: string) { const policy = ReportUtils.getPolicy(policyID); @@ -3922,7 +3902,6 @@ export { renamePolicyCategory, clearCategoryErrors, setWorkspacePayer, - clearWorkspacePayerError, setWorkspaceReimbursement, openPolicyWorkflowsPage, setPolicyRequiresTag, @@ -3944,10 +3923,6 @@ export { clearWorkspaceReimbursementErrors, deleteWorkspaceCategories, setWorkspaceTagEnabled, - clearWorkspaceApprovalError, - clearWorkspaceAutoReportingError, - clearWorkspaceAutoReportingFrequencyError, - clearWorkspaceAutoReportingOffsetError, - clearWorkspaceGeneralSettingError, + clearPolicyErrorField, hasValidCurrencyForDirectReimbursement, }; From 9f0a1fe922ec21cc534444d647dc3d3d5ca4ae26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Tue, 19 Mar 2024 09:12:58 +0100 Subject: [PATCH 15/30] use const for policy collection fields --- src/pages/workspace/WorkspaceProfilePage.tsx | 8 ++++---- .../WorkspaceAutoReportingFrequencyPage.tsx | 8 ++++---- .../workflows/WorkspaceWorkflowsPage.tsx | 16 ++++++++-------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/pages/workspace/WorkspaceProfilePage.tsx b/src/pages/workspace/WorkspaceProfilePage.tsx index 57b3c732de8b..0ccc221abc6e 100644 --- a/src/pages/workspace/WorkspaceProfilePage.tsx +++ b/src/pages/workspace/WorkspaceProfilePage.tsx @@ -165,8 +165,8 @@ function WorkspaceProfilePage({policy, currencyList = {}, route}: WorkSpaceProfi {(!StringUtils.isEmptyString(policy?.description ?? '') || !readOnly) && ( Policy.clearWorkspaceGeneralSettingError(policy?.id ?? '')} + errors={ErrorUtils.getLatestErrorField(policy ?? {}, CONST.POLICY.COLLECTION_FIELDS.DESCRIPTION)} + onClose={() => Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_FIELDS.DESCRIPTION)} > Policy.clearWorkspaceGeneralSettingError(policy?.id ?? '')} + errors={ErrorUtils.getLatestErrorField(policy ?? {}, CONST.POLICY.COLLECTION_FIELDS.GENERAL_SETTINGS)} + onClose={() => Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_FIELDS.GENERAL_SETTINGS)} errorRowStyles={[styles.mt2]} > diff --git a/src/pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage.tsx b/src/pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage.tsx index 5514d0c8a218..8a8d83f40928 100644 --- a/src/pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage.tsx @@ -83,8 +83,8 @@ function WorkspaceAutoReportingFrequencyPage({policy}: WorkspaceAutoReportingFre const monthlyFrequencyDetails = () => ( Policy.clearWorkspaceAutoReportingOffsetError(policy?.id ?? '')} + errors={ErrorUtils.getLatestErrorField(policy ?? {}, CONST.POLICY.COLLECTION_FIELDS.AUTOREPORTING_OFFSET)} + onClose={() => Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_FIELDS.AUTOREPORTING_OFFSET)} errorRowStyles={[styles.ml7]} > Policy.clearWorkspaceAutoReportingFrequencyError(policy?.id ?? '')} + errors={ErrorUtils.getLatestErrorField(policy ?? {}, CONST.POLICY.COLLECTION_FIELDS.AUTOREPORTING_FREQUENCY)} + onClose={() => Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_FIELDS.AUTOREPORTING_FREQUENCY)} > Policy.clearWorkspaceAutoReportingError(policy?.id ?? ''), + errors: ErrorUtils.getLatestErrorField(policy ?? {}, CONST.POLICY.COLLECTION_FIELDS.AUTOREPORTING), + onCloseError: () => Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_FIELDS.AUTOREPORTING), }, ] : []), @@ -153,8 +153,8 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses ), isActive: (policy?.isAutoApprovalEnabled && !hasApprovalError) ?? false, pendingAction: policy?.pendingFields?.approvalMode, - errors: ErrorUtils.getLatestErrorField(policy ?? {}, 'approvalMode'), - onCloseError: () => Policy.clearWorkspaceApprovalError(policy?.id ?? ''), + errors: ErrorUtils.getLatestErrorField(policy ?? {}, CONST.POLICY.COLLECTION_FIELDS.APPROVAL_MODE), + onCloseError: () => Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_FIELDS.APPROVAL_MODE), }, { icon: Illustrations.WalletAlt, @@ -189,8 +189,8 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses {hasVBA && ( Policy.clearWorkspacePayerError(policy?.id ?? '')} + errors={ErrorUtils.getLatestErrorField(policy ?? {}, CONST.POLICY.COLLECTION_FIELDS.REIMBURSER_EMAIL)} + onClose={() => Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_FIELDS.REIMBURSER_EMAIL)} errorRowStyles={[styles.ml7]} > Policy.clearWorkspaceReimbursementErrors(policy?.id ?? ''), + errors: ErrorUtils.getLatestErrorField(policy ?? {}, CONST.POLICY.COLLECTION_FIELDS.REIMBURSEMENT_CHOICE), + onCloseError: () => Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_FIELDS.REIMBURSEMENT_CHOICE), }, ]; }, [ From 7343b48ce641ed38f0992ddb4d5c2a69b3ae95c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Tue, 19 Mar 2024 09:13:40 +0100 Subject: [PATCH 16/30] remove currency not available as direct reimbursement --- src/CONST.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CONST.ts b/src/CONST.ts index f3a4edc9911a..0135070cdff3 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -499,7 +499,7 @@ const CONST = { EUR: 'EUR', }, get DIRECT_REIMBURSEMENT_CURRENCIES() { - return [this.CURRENCY.USD, this.CURRENCY.AUD, this.CURRENCY.CAD, this.CURRENCY.GBP, this.CURRENCY.NZD, this.CURRENCY.EUR]; + return [this.CURRENCY.USD, this.CURRENCY.AUD, this.CURRENCY.CAD, this.CURRENCY.GBP, this.CURRENCY.EUR]; }, EXAMPLE_PHONE_NUMBER: '+15005550006', CONCIERGE_CHAT_NAME: 'Concierge', From b7b2a0732515cb8bb50f8fcc257a660fa36ae501 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Tue, 19 Mar 2024 09:32:10 +0100 Subject: [PATCH 17/30] improved logic for hasValidCurrencyForDirectReimbursement() --- src/libs/actions/Policy.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index 73baf68f8c74..11df039e59ce 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -129,14 +129,6 @@ type WorkspaceMembersRoleData = { role: typeof CONST.POLICY.ROLE.ADMIN | typeof CONST.POLICY.ROLE.USER; }; -const CURRENCY_AU = 'AUD'; -const CURRENCY_CA = 'CAD'; -const CURRENCY_GB = 'GBP'; -const CURRENCY_US = 'USD'; -const CURRENCY_EUR = 'EUR'; - -const DIRECT_REIMBURSEMENT_CURRENCIES: string[] = [CURRENCY_AU, CURRENCY_CA, CURRENCY_EUR, CURRENCY_GB, CURRENCY_US]; - const allPolicies: OnyxCollection = {}; Onyx.connect({ key: ONYXKEYS.COLLECTION.POLICY, @@ -258,7 +250,7 @@ function updateLastAccessedWorkspace(policyID: OnyxEntry) { } function hasValidCurrencyForDirectReimbursement(currency: string) { - return DIRECT_REIMBURSEMENT_CURRENCIES.includes(currency); + return CONST.DIRECT_REIMBURSEMENT_CURRENCIES.includes(currency as typeof CONST.DIRECT_REIMBURSEMENT_CURRENCIES[number]); } /** * Check if the user has any active free policies (aka workspaces) From 84a1c834e025384f0bc9267ac486e072a3c9cd33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Tue, 19 Mar 2024 09:35:23 +0100 Subject: [PATCH 18/30] improved naming --- src/libs/actions/Policy.ts | 8 ++++---- src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index 11df039e59ce..785bdc81dc85 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -249,8 +249,8 @@ function updateLastAccessedWorkspace(policyID: OnyxEntry) { Onyx.set(ONYXKEYS.LAST_ACCESSED_WORKSPACE_POLICY_ID, policyID); } -function hasValidCurrencyForDirectReimbursement(currency: string) { - return CONST.DIRECT_REIMBURSEMENT_CURRENCIES.includes(currency as typeof CONST.DIRECT_REIMBURSEMENT_CURRENCIES[number]); +function hasCurrencySupportedForDirectReimbursement(currency: string) { + return CONST.DIRECT_REIMBURSEMENT_CURRENCIES.includes(currency as (typeof CONST.DIRECT_REIMBURSEMENT_CURRENCIES)[number]); } /** * Check if the user has any active free policies (aka workspaces) @@ -666,7 +666,7 @@ function setWorkspacePayer(policyID: string, reimburserEmail: string, reimburser function clearPolicyErrorField(policyID: string, fieldName: string) { Onyx.merge(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {errorFields: {[fieldName]: null}}); -} +} function setWorkspaceReimbursement(policyID: string, reimbursementChoice: ValueOf, reimburserAccountID: number, reimburserEmail: string) { const policy = ReportUtils.getPolicy(policyID); @@ -3916,5 +3916,5 @@ export { deleteWorkspaceCategories, setWorkspaceTagEnabled, clearPolicyErrorField, - hasValidCurrencyForDirectReimbursement, + hasCurrencySupportedForDirectReimbursement, }; diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx index 3c15710b4999..2df331e06c07 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx @@ -176,7 +176,7 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses title={hasVBA ? translate('common.bankAccount') : translate('workflowsPage.connectBankAccount')} description={state === BankAccount.STATE.OPEN ? bankDisplayName : undefined} onPress={() => { - if (!Policy.hasValidCurrencyForDirectReimbursement(policy?.outputCurrency ?? '')) { + if (!Policy.hasCurrencySupportedForDirectReimbursement(policy?.outputCurrency ?? '')) { setIsCurrencyModalOpen(true); return; } From a2a788ee8f513d1df73604526af36f650efa8f0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Tue, 19 Mar 2024 16:48:04 +0100 Subject: [PATCH 19/30] rename method and filter EUR currency for direct reimbursement as it's not supported yet --- src/libs/actions/Policy.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index 4f20c927bbe5..e83550674af5 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -250,9 +250,10 @@ function updateLastAccessedWorkspace(policyID: OnyxEntry) { Onyx.set(ONYXKEYS.LAST_ACCESSED_WORKSPACE_POLICY_ID, policyID); } -function hasCurrencySupportedForDirectReimbursement(currency: string) { - return CONST.DIRECT_REIMBURSEMENT_CURRENCIES.includes(currency as (typeof CONST.DIRECT_REIMBURSEMENT_CURRENCIES)[number]); +function isCurrencySupportedForDirectReimbursement(currency: string) { + return CONST.DIRECT_REIMBURSEMENT_CURRENCIES.filter(currency => currency !== CONST.CURRENCY.EUR).includes(currency as (typeof CONST.DIRECT_REIMBURSEMENT_CURRENCIES)[number]); } + /** * Check if the user has any active free policies (aka workspaces) */ @@ -4139,5 +4140,5 @@ export { setForeignCurrencyDefault, setPolicyCustomTaxName, clearPolicyErrorField, - hasCurrencySupportedForDirectReimbursement, + isCurrencySupportedForDirectReimbursement, }; From 428bbe6b0c632f049c45b93b19568633baa19b04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Tue, 19 Mar 2024 16:48:30 +0100 Subject: [PATCH 20/30] fix reimbursement choice --- .../workspace/workflows/WorkspaceWorkflowsPage.tsx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx index 2df331e06c07..4e96318ea433 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx @@ -160,8 +160,14 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses icon: Illustrations.WalletAlt, title: translate('workflowsPage.makeOrTrackPaymentsTitle'), subtitle: translate('workflowsPage.makeOrTrackPaymentsDescription'), - onToggle: () => { - const newReimbursementChoice = !hasVBA ? CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL : CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES; + onToggle: (isEnabled: boolean) => { + let newReimbursementChoice; + if (!isEnabled) { + newReimbursementChoice = CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO; + } else { + newReimbursementChoice = hasVBA ? CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES : CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL; + } + const newReimburserAccountID = // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing PersonalDetailsUtils.getPersonalDetailByEmail(policy?.reimburserEmail ?? '')?.accountID || policy?.reimburserAccountID || policy?.ownerAccountID; @@ -176,7 +182,7 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses title={hasVBA ? translate('common.bankAccount') : translate('workflowsPage.connectBankAccount')} description={state === BankAccount.STATE.OPEN ? bankDisplayName : undefined} onPress={() => { - if (!Policy.hasCurrencySupportedForDirectReimbursement(policy?.outputCurrency ?? '')) { + if (!Policy.isCurrencySupportedForDirectReimbursement(policy?.outputCurrency ?? '')) { setIsCurrencyModalOpen(true); return; } @@ -209,7 +215,7 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses ), isEndOptionRow: true, - isActive: policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES, + isActive: policy?.reimbursementChoice !== CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO, pendingAction: policy?.pendingFields?.reimbursementChoice, errors: ErrorUtils.getLatestErrorField(policy ?? {}, CONST.POLICY.COLLECTION_FIELDS.REIMBURSEMENT_CHOICE), onCloseError: () => Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_FIELDS.REIMBURSEMENT_CHOICE), From 39f9161f86996dda47a691bd117ea5163b32edec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Tue, 19 Mar 2024 16:52:05 +0100 Subject: [PATCH 21/30] fix lint --- src/libs/actions/Policy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index e83550674af5..966704108593 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -251,7 +251,7 @@ function updateLastAccessedWorkspace(policyID: OnyxEntry) { } function isCurrencySupportedForDirectReimbursement(currency: string) { - return CONST.DIRECT_REIMBURSEMENT_CURRENCIES.filter(currency => currency !== CONST.CURRENCY.EUR).includes(currency as (typeof CONST.DIRECT_REIMBURSEMENT_CURRENCIES)[number]); + return CONST.DIRECT_REIMBURSEMENT_CURRENCIES.filter((c) => c !== CONST.CURRENCY.EUR).includes(currency as (typeof CONST.DIRECT_REIMBURSEMENT_CURRENCIES)[number]); } /** From cf6a4bd2eddfaeea68a5fbbb0ddc748f348f7137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Tue, 19 Mar 2024 16:52:11 +0100 Subject: [PATCH 22/30] fix style --- src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx index 4e96318ea433..87dc11931da8 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx @@ -167,7 +167,7 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses } else { newReimbursementChoice = hasVBA ? CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES : CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL; } - + const newReimburserAccountID = // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing PersonalDetailsUtils.getPersonalDetailByEmail(policy?.reimburserEmail ?? '')?.accountID || policy?.reimburserAccountID || policy?.ownerAccountID; From c2a82ca90ce64a20517c5cb3f41d8d53a4f74771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Tue, 19 Mar 2024 17:04:13 +0100 Subject: [PATCH 23/30] fix edge case --- src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx index 87dc11931da8..f6ae862659de 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx @@ -162,8 +162,12 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses subtitle: translate('workflowsPage.makeOrTrackPaymentsDescription'), onToggle: (isEnabled: boolean) => { let newReimbursementChoice; + if (!isEnabled) { newReimbursementChoice = CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO; + } else if (hasVBA && !Policy.isCurrencySupportedForDirectReimbursement(policy?.outputCurrency ?? '')) { + setIsCurrencyModalOpen(true); + return; } else { newReimbursementChoice = hasVBA ? CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES : CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL; } From 801c6ae87475e47566af0a378d0dd112ffcd8fea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Wed, 20 Mar 2024 09:49:26 +0100 Subject: [PATCH 24/30] fix currency supported --- src/libs/actions/Policy.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index 907424debcf1..f0d3ed267e6f 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -250,8 +250,12 @@ function updateLastAccessedWorkspace(policyID: OnyxEntry) { Onyx.set(ONYXKEYS.LAST_ACCESSED_WORKSPACE_POLICY_ID, policyID); } +/** + * Checks if the currency is supported for direct reimbursement + * USD currency is the only one supported in NewDot for now + */ function isCurrencySupportedForDirectReimbursement(currency: string) { - return CONST.DIRECT_REIMBURSEMENT_CURRENCIES.filter((c) => c !== CONST.CURRENCY.EUR).includes(currency as (typeof CONST.DIRECT_REIMBURSEMENT_CURRENCIES)[number]); + return currency === CONST.CURRENCY.USD; } /** From fc71b6dee7c81a38bd849757538e4a4f6ae09f59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Wed, 20 Mar 2024 14:57:36 +0100 Subject: [PATCH 25/30] improved naming --- src/CONST.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CONST.ts b/src/CONST.ts index 9f363691ead7..74298b47b9bd 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1487,7 +1487,7 @@ const CONST = { DISABLE: 'disable', ENABLE: 'enable', }, - COLLECTION_FIELDS: { + COLLECTION_KEYS: { DESCRIPTION: 'description', REIMBURSER_EMAIL: 'reimburserEmail', REIMBURSEMENT_CHOICE: 'reimbursementChoice', From 45c79232471ae1248a14ac4c3c7cd9aad016f41b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Wed, 20 Mar 2024 14:58:00 +0100 Subject: [PATCH 26/30] use new naming for const collection keys --- src/pages/workspace/WorkspaceProfilePage.tsx | 8 ++++---- .../workflows/WorkspaceAutoReportingFrequencyPage.tsx | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/pages/workspace/WorkspaceProfilePage.tsx b/src/pages/workspace/WorkspaceProfilePage.tsx index 215c94616470..7169d8a4ab7c 100644 --- a/src/pages/workspace/WorkspaceProfilePage.tsx +++ b/src/pages/workspace/WorkspaceProfilePage.tsx @@ -176,8 +176,8 @@ function WorkspaceProfilePage({policy, currencyList = {}, route}: WorkSpaceProfi {(!StringUtils.isEmptyString(policy?.description ?? '') || !readOnly) && ( Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_FIELDS.DESCRIPTION)} + errors={ErrorUtils.getLatestErrorField(policy ?? {}, CONST.POLICY.COLLECTION_KEYS.DESCRIPTION)} + onClose={() => Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_KEYS.DESCRIPTION)} > Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_FIELDS.GENERAL_SETTINGS)} + errors={ErrorUtils.getLatestErrorField(policy ?? {}, CONST.POLICY.COLLECTION_KEYS.GENERAL_SETTINGS)} + onClose={() => Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_KEYS.GENERAL_SETTINGS)} errorRowStyles={[styles.mt2]} > diff --git a/src/pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage.tsx b/src/pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage.tsx index 8a8d83f40928..034cc1c001ed 100644 --- a/src/pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage.tsx @@ -83,8 +83,8 @@ function WorkspaceAutoReportingFrequencyPage({policy}: WorkspaceAutoReportingFre const monthlyFrequencyDetails = () => ( Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_FIELDS.AUTOREPORTING_OFFSET)} + errors={ErrorUtils.getLatestErrorField(policy ?? {}, CONST.POLICY.COLLECTION_KEYS.AUTOREPORTING_OFFSET)} + onClose={() => Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_KEYS.AUTOREPORTING_OFFSET)} errorRowStyles={[styles.ml7]} > Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_FIELDS.AUTOREPORTING_FREQUENCY)} + errors={ErrorUtils.getLatestErrorField(policy ?? {}, CONST.POLICY.COLLECTION_KEYS.AUTOREPORTING_FREQUENCY)} + onClose={() => Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_KEYS.AUTOREPORTING_FREQUENCY)} > Date: Wed, 20 Mar 2024 14:58:27 +0100 Subject: [PATCH 27/30] fix toggle logic --- .../workflows/WorkspaceWorkflowsPage.tsx | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx index 838be3ca538e..9b394fc5d89f 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx @@ -126,8 +126,8 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses ), isActive: (policy?.harvesting?.enabled && policy.autoReportingFrequency !== CONST.POLICY.AUTO_REPORTING_FREQUENCIES.INSTANT && !hasDelayedSubmissionError) ?? false, pendingAction: policy?.pendingFields?.autoReporting, - errors: ErrorUtils.getLatestErrorField(policy ?? {}, CONST.POLICY.COLLECTION_FIELDS.AUTOREPORTING), - onCloseError: () => Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_FIELDS.AUTOREPORTING), + errors: ErrorUtils.getLatestErrorField(policy ?? {}, CONST.POLICY.COLLECTION_KEYS.AUTOREPORTING), + onCloseError: () => Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_KEYS.AUTOREPORTING), }, ] : []), @@ -153,37 +153,35 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses ), isActive: (policy?.approvalMode === CONST.POLICY.APPROVAL_MODE.BASIC && !hasApprovalError) ?? false, pendingAction: policy?.pendingFields?.approvalMode, - errors: ErrorUtils.getLatestErrorField(policy ?? {}, CONST.POLICY.COLLECTION_FIELDS.APPROVAL_MODE), - onCloseError: () => Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_FIELDS.APPROVAL_MODE), + errors: ErrorUtils.getLatestErrorField(policy ?? {}, CONST.POLICY.COLLECTION_KEYS.APPROVAL_MODE), + onCloseError: () => Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_KEYS.APPROVAL_MODE), }, { icon: Illustrations.WalletAlt, title: translate('workflowsPage.makeOrTrackPaymentsTitle'), subtitle: translate('workflowsPage.makeOrTrackPaymentsDescription'), - onToggle: (isEnabled: boolean) => { - let newReimbursementChoice; + onToggle: () => { + const isActive = policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES; + + const newReimbursementChoice = isActive ? CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL : CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES; + + const shouldUseDirectReimbursement = !isActive && Policy.isCurrencySupportedForDirectReimbursement(policy?.outputCurrency ?? ''); - if (!isEnabled) { - newReimbursementChoice = CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO; - } else if (hasVBA && !Policy.isCurrencySupportedForDirectReimbursement(policy?.outputCurrency ?? '')) { - setIsCurrencyModalOpen(true); - return; - } else { - newReimbursementChoice = hasVBA ? CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES : CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL; - } + // If trying to enable direct reimbursement and currency is not supported, default to manual (indirect) reimbursement + const effectiveReimbursementChoice = shouldUseDirectReimbursement ? newReimbursementChoice : CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL; const newReimburserAccountID = // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing PersonalDetailsUtils.getPersonalDetailByEmail(policy?.reimburserEmail ?? '')?.accountID || policy?.reimburserAccountID || policy?.ownerAccountID; const newReimburserEmail = PersonalDetailsUtils.getPersonalDetailsByIDs([newReimburserAccountID ?? 0], session?.accountID ?? 0)?.[0]?.login; - Policy.setWorkspaceReimbursement(policy?.id ?? '', newReimbursementChoice, newReimburserAccountID ?? 0, newReimburserEmail ?? ''); + Policy.setWorkspaceReimbursement(policy?.id ?? '', effectiveReimbursementChoice, newReimburserAccountID ?? 0, newReimburserEmail ?? ''); }, subMenuItems: ( <> { if (!Policy.isCurrencySupportedForDirectReimbursement(policy?.outputCurrency ?? '')) { @@ -196,11 +194,11 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses wrapperStyle={containerStyle} hoverAndPressStyle={[styles.mr0, styles.br2]} /> - {hasVBA && ( + {hasVBA && policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES && ( Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_FIELDS.REIMBURSER_EMAIL)} + errors={ErrorUtils.getLatestErrorField(policy ?? {}, CONST.POLICY.COLLECTION_KEYS.REIMBURSER_EMAIL)} + onClose={() => Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_KEYS.REIMBURSER_EMAIL)} errorRowStyles={[styles.ml7]} > ), isEndOptionRow: true, - isActive: policy?.reimbursementChoice !== CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO, + isActive: policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES, pendingAction: policy?.pendingFields?.reimbursementChoice, - errors: ErrorUtils.getLatestErrorField(policy ?? {}, CONST.POLICY.COLLECTION_FIELDS.REIMBURSEMENT_CHOICE), - onCloseError: () => Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_FIELDS.REIMBURSEMENT_CHOICE), + errors: ErrorUtils.getLatestErrorField(policy ?? {}, CONST.POLICY.COLLECTION_KEYS.REIMBURSEMENT_CHOICE), + onCloseError: () => Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_KEYS.REIMBURSEMENT_CHOICE), }, ]; }, [ From 172c8b3b6ffc110aa0e86bffea6b021f3ed72e28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Wed, 20 Mar 2024 15:17:56 +0100 Subject: [PATCH 28/30] improved toggle logic --- .../workflows/WorkspaceWorkflowsPage.tsx | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx index 9b394fc5d89f..819a32571c4d 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx @@ -161,14 +161,14 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses title: translate('workflowsPage.makeOrTrackPaymentsTitle'), subtitle: translate('workflowsPage.makeOrTrackPaymentsDescription'), onToggle: () => { - const isActive = policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES; - - const newReimbursementChoice = isActive ? CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL : CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES; - - const shouldUseDirectReimbursement = !isActive && Policy.isCurrencySupportedForDirectReimbursement(policy?.outputCurrency ?? ''); + const shouldUseDirectReimbursement = + policy?.reimbursementChoice !== CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES && + Policy.isCurrencySupportedForDirectReimbursement(policy?.outputCurrency ?? ''); // If trying to enable direct reimbursement and currency is not supported, default to manual (indirect) reimbursement - const effectiveReimbursementChoice = shouldUseDirectReimbursement ? newReimbursementChoice : CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL; + const effectiveReimbursementChoice = shouldUseDirectReimbursement + ? CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES + : CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL; const newReimburserAccountID = // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing @@ -181,7 +181,11 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses { if (!Policy.isCurrencySupportedForDirectReimbursement(policy?.outputCurrency ?? '')) { From a932d16db2cdcc9533ed4fe4a71efb8c53dc2b0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Wed, 20 Mar 2024 15:56:32 +0100 Subject: [PATCH 29/30] fix style --- .../WorkspaceAutoReportingFrequencyPage.tsx | 12 +++++------ .../workflows/WorkspaceWorkflowsPage.tsx | 20 +++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage.tsx b/src/pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage.tsx index 88b82d6b3cba..1dd65ffb2390 100644 --- a/src/pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceAutoReportingFrequencyPage.tsx @@ -133,18 +133,18 @@ function WorkspaceAutoReportingFrequencyPage({policy, route}: WorkspaceAutoRepor title={translate('workflowsPage.submissionFrequency')} onBackButtonPress={Navigation.goBack} /> - Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_KEYS.AUTOREPORTING_FREQUENCY)} - > + Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_KEYS.AUTOREPORTING_FREQUENCY)} + > item.text} /> - + ); diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx index dabda756cbc7..8d4c68ba0d1f 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx @@ -292,16 +292,16 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses keyExtractor={(item: ToggleSettingOptionRowProps) => item.title} /> setIsCurrencyModalOpen(false)} - prompt={translate('workspace.bankAccount.updateCurrencyPrompt')} - confirmText={translate('workspace.bankAccount.updateToUSD')} - cancelText={translate('common.cancel')} - danger - /> - + title={translate('workspace.bankAccount.workspaceCurrency')} + isVisible={isCurrencyModalOpen} + onConfirm={confirmCurrencyChangeAndHideModal} + onCancel={() => setIsCurrencyModalOpen(false)} + prompt={translate('workspace.bankAccount.updateCurrencyPrompt')} + confirmText={translate('workspace.bankAccount.updateToUSD')} + cancelText={translate('common.cancel')} + danger + /> + From adb5d5e5f9d449bfd032849359a5443e2b249ffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucien=20Akchot=C3=A9?= Date: Wed, 20 Mar 2024 17:45:05 +0100 Subject: [PATCH 30/30] fix toggle logic --- .../workflows/WorkspaceWorkflowsPage.tsx | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx index 8d4c68ba0d1f..5bcb631c21b0 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx @@ -161,21 +161,21 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses icon: Illustrations.WalletAlt, title: translate('workflowsPage.makeOrTrackPaymentsTitle'), subtitle: translate('workflowsPage.makeOrTrackPaymentsDescription'), - onToggle: () => { - const shouldUseDirectReimbursement = - policy?.reimbursementChoice !== CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES && - Policy.isCurrencySupportedForDirectReimbursement(policy?.outputCurrency ?? ''); - - // If trying to enable direct reimbursement and currency is not supported, default to manual (indirect) reimbursement - const effectiveReimbursementChoice = shouldUseDirectReimbursement - ? CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES - : CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL; + onToggle: (isEnabled: boolean) => { + let newReimbursementChoice; + if (!isEnabled) { + newReimbursementChoice = CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO; + } else if (hasVBA && !Policy.isCurrencySupportedForDirectReimbursement(policy?.outputCurrency ?? '')) { + newReimbursementChoice = CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL; + } else { + newReimbursementChoice = hasVBA ? CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES : CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_MANUAL; + } const newReimburserAccountID = // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing PersonalDetailsUtils.getPersonalDetailByEmail(policy?.reimburserEmail ?? '')?.accountID || policy?.reimburserAccountID || policy?.ownerAccountID; const newReimburserEmail = PersonalDetailsUtils.getPersonalDetailsByIDs([newReimburserAccountID ?? 0], session?.accountID ?? 0)?.[0]?.login; - Policy.setWorkspaceReimbursement(policy?.id ?? '', effectiveReimbursementChoice, newReimburserAccountID ?? 0, newReimburserEmail ?? ''); + Policy.setWorkspaceReimbursement(policy?.id ?? '', newReimbursementChoice, newReimburserAccountID ?? 0, newReimburserEmail ?? ''); }, subMenuItems: ( <> @@ -222,7 +222,7 @@ function WorkspaceWorkflowsPage({policy, betas, route, reimbursementAccount, ses ), isEndOptionRow: true, - isActive: policy?.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES, + isActive: policy?.reimbursementChoice !== CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO, pendingAction: policy?.pendingFields?.reimbursementChoice, errors: ErrorUtils.getLatestErrorField(policy ?? {}, CONST.POLICY.COLLECTION_KEYS.REIMBURSEMENT_CHOICE), onCloseError: () => Policy.clearPolicyErrorField(policy?.id ?? '', CONST.POLICY.COLLECTION_KEYS.REIMBURSEMENT_CHOICE),