Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Swap from withPolicy to withPolicyConnections for advanced Quickbooks pages #40718

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
827b1f2
swap withPolicy to withPolicyConnections for advanced page
teneeto Apr 22, 2024
c648855
Merge branch 'main' of github.com:teneeto/Expensify into qbo-hoc-with…
teneeto Apr 24, 2024
9ae3099
remove drafts
teneeto Apr 24, 2024
213aef4
update selected qbo and invoice collection name
teneeto Apr 24, 2024
fea4550
Merge branch 'main' of github.com:teneeto/Expensify into qbo-hoc-with…
teneeto Apr 25, 2024
1bf7048
Merge branch 'main' of github.com:teneeto/Expensify into qbo-hoc-with…
teneeto Apr 25, 2024
a310abb
use WithPolicyConnectionsProps
teneeto Apr 25, 2024
c064fc6
use WithPolicyConnectionsProps
teneeto Apr 25, 2024
bd5f257
use WithPolicyConnectionsProps
teneeto Apr 25, 2024
83561ec
add sync reimbursed to qboToggleSettingItems
teneeto Apr 25, 2024
d0ff87e
remove all horizontal line spacer view
teneeto Apr 25, 2024
3301d0a
move sync reimbursed items to syncReimbursedSubMenuItems
teneeto Apr 25, 2024
21d3840
update translations
teneeto Apr 25, 2024
b9decde
use new translations
teneeto Apr 25, 2024
730ec7b
remove collectionAccountDescription
teneeto Apr 25, 2024
2cab80f
remove menuItem
teneeto Apr 25, 2024
b50e330
add vertical margins
teneeto Apr 25, 2024
786321f
enable sync reimbursed accounts for any available account
teneeto Apr 25, 2024
99bf390
set isActive to isSyncReimbursedSwitchOn
teneeto Apr 25, 2024
20f439a
use updated translation string
teneeto Apr 25, 2024
d0b770c
use updated translation string
teneeto Apr 25, 2024
6749014
Update src/languages/es.ts
teneeto Apr 25, 2024
7339458
Update src/languages/es.ts
teneeto Apr 25, 2024
9235dec
Update src/languages/es.ts
teneeto Apr 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1926,10 +1926,9 @@ export default {
createEntitiesDescription:
'Expensify will automatically create a vendor in Quickbooks, if one does not exist. Expensify will also automatically create a customer when exporting invoices.',
reimbursedReports: 'Sync reimbursed reports',
reimbursedReportsDescription: 'Any time report is paid using Expensify ACH, the corresponding bill payment will be created in the Quickbooks accounts below.',
qboAccount: 'Quickbooks account',
collectionAccount: 'Invoice collection account',
collectionAccountDescription: 'Once invoices have been paid, the payment will appear in the account configured below.',
reimbursedReportsDescription: 'Any time a report is paid using Expensify ACH, the corresponding bill payment will be created in the Quickbooks account below.',
qboBillPaymentAccount: 'QuickBooks bill payment account',
qboInvoiceCollectionAccount: 'QuickBooks invoice collections account',
accountSelectDescription:
"As you've enabled sync reimbursed reports, you will need select the bank account your reimbursements are coming out of, and we'll create the payment in QuickBooks.",
invoiceAccountSelectDescription:
Expand Down
7 changes: 3 additions & 4 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1953,10 +1953,9 @@ export default {
'Expensify creará automáticamente un proveedor en Quickbooks, si no existe. Expensify también creará automáticamente un cliente al exportar facturas.',
reimbursedReports: 'Sincronizar informes reembolsados',
reimbursedReportsDescription:
'Cada vez que se pague un informe utilizando Expensify ACH, se creará el pago de la factura correspondiente en las cuentas de Quickbooks indicadas a continuación.',
qboAccount: 'Cuenta Quickbooks',
collectionAccount: 'Cuenta de cobro de facturas',
collectionAccountDescription: 'Una vez abonadas las facturas, el pago aparecerá en la cuenta configurada a continuación.',
'Cada vez que se pague un informe utilizando Expensify ACH, se creará el correspondiente pago de la factura en la cuenta de Quickbooks indicadas a continuación.',
qboBillPaymentAccount: 'Cuenta de pago de las facturas de QuickBooks',
qboInvoiceCollectionAccount: 'Cuenta de cobro de las facturas QuickBooks',
accountSelectDescription:
'Como has activado la sincronización de los informes de reembolso, tendrás que seleccionar la cuenta bancaria de la que saldrán tus reembolsos y crearemos el pago en QuickBooks.',
invoiceAccountSelectDescription:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,42 +13,33 @@ import Navigation from '@libs/Navigation/Navigation';
import AdminPolicyAccessOrNotFoundWrapper from '@pages/workspace/AdminPolicyAccessOrNotFoundWrapper';
import FeatureEnabledAccessOrNotFoundWrapper from '@pages/workspace/FeatureEnabledAccessOrNotFoundWrapper';
import PaidPolicyAccessOrNotFoundWrapper from '@pages/workspace/PaidPolicyAccessOrNotFoundWrapper';
import withPolicy from '@pages/workspace/withPolicy';
import type {WithPolicyProps} from '@pages/workspace/withPolicy';
import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections';
import withPolicyConnections from '@pages/workspace/withPolicyConnections';
import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';

type SelectorType = ListItem & {
value: string;
};

// TODO: remove once UI is approved
const DRAFT = [
{name: 'Croissant Co Payroll Account', id: 'Croissant Co Payroll Account'},
{name: 'Croissant Co Money in Clearing', id: 'Croissant Co Money in Clearing'},
{name: 'Croissant Co Debts and Loans', id: 'Croissant Co Debts and Loans'},
];

function QuickbooksAccountSelectPage({policy}: WithPolicyProps) {
function QuickbooksAccountSelectPage({policy}: WithPolicyConnectionsProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();

const selectedAccount = DRAFT[0].id; // selected

const policyID = policy?.id ?? '';
const {bankAccounts, creditCards} = policy?.connections?.quickbooksOnline?.data ?? {};
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
const accountOptions = useMemo(() => DRAFT || [...(bankAccounts ?? []), ...(creditCards ?? [])], [bankAccounts, creditCards]);
const {reimbursementAccountID} = policy?.connections?.quickbooksOnline?.config ?? {};
const accountOptions = useMemo(() => [...(bankAccounts ?? []), ...(creditCards ?? [])], [bankAccounts, creditCards]);

const qboOnlineSelectorOptions = useMemo<SelectorType[]>(
() =>
accountOptions?.map(({id, name}) => ({
value: id,
text: name,
keyForList: id,
isSelected: selectedAccount === id,
isSelected: reimbursementAccountID === id,
})),
[selectedAccount, accountOptions],
[reimbursementAccountID, accountOptions],
);
const listHeaderComponent = useMemo(
() => (
Expand Down Expand Up @@ -80,7 +71,7 @@ function QuickbooksAccountSelectPage({policy}: WithPolicyProps) {
includeSafeAreaPaddingBottom={false}
testID={QuickbooksAccountSelectPage.displayName}
>
<HeaderWithBackButton title={translate('workspace.qbo.advancedConfig.qboAccount')} />
<HeaderWithBackButton title={translate('workspace.qbo.advancedConfig.qboBillPaymentAccount')} />

<SelectionList
sections={[{data: qboOnlineSelectorOptions}]}
Expand All @@ -98,4 +89,4 @@ function QuickbooksAccountSelectPage({policy}: WithPolicyProps) {

QuickbooksAccountSelectPage.displayName = 'QuickbooksAccountSelectPage';

export default withPolicy(QuickbooksAccountSelectPage);
export default withPolicyConnections(QuickbooksAccountSelectPage);
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import React from 'react';
import React, {useMemo} from 'react';
import {View} from 'react-native';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import MenuItem from '@components/MenuItem';
import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
import OfflineWithFeedback from '@components/OfflineWithFeedback';
import ScreenWrapper from '@components/ScreenWrapper';
import ScrollView from '@components/ScrollView';
import SpacerView from '@components/SpacerView';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import useWaitForNavigation from '@hooks/useWaitForNavigation';
Expand All @@ -16,24 +14,62 @@ import Navigation from '@libs/Navigation/Navigation';
import AdminPolicyAccessOrNotFoundWrapper from '@pages/workspace/AdminPolicyAccessOrNotFoundWrapper';
import FeatureEnabledAccessOrNotFoundWrapper from '@pages/workspace/FeatureEnabledAccessOrNotFoundWrapper';
import PaidPolicyAccessOrNotFoundWrapper from '@pages/workspace/PaidPolicyAccessOrNotFoundWrapper';
import withPolicy from '@pages/workspace/withPolicy';
import type {WithPolicyProps} from '@pages/workspace/withPolicy';
import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections';
import withPolicyConnections from '@pages/workspace/withPolicyConnections';
import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow';
import type {ToggleSettingOptionRowProps} from '@pages/workspace/workflows/ToggleSettingsOptionRow';
import * as Policy from '@userActions/Policy';
import CONST from '@src/CONST';
import ROUTES from '@src/ROUTES';

function QuickbooksAdvancedPage({policy}: WithPolicyProps) {
function QuickbooksAdvancedPage({policy}: WithPolicyConnectionsProps) {
const styles = useThemeStyles();
const waitForNavigate = useWaitForNavigation();
const {translate} = useLocalize();

const policyID = policy?.id ?? '';
const qboConfig = policy?.connections?.quickbooksOnline?.config;
const {autoSync, syncPeople, autoCreateVendor, pendingFields, collectionAccountID, errorFields} = qboConfig ?? {};
const {autoSync, syncPeople, autoCreateVendor, pendingFields, collectionAccountID, reimbursementAccountID, errorFields} = qboConfig ?? {};
const {bankAccounts, creditCards, otherCurrentAssetAccounts} = policy?.connections?.quickbooksOnline?.data ?? {};

const qboAccountOptions = useMemo(() => [...(bankAccounts ?? []), ...(creditCards ?? [])], [bankAccounts, creditCards]);
const invoiceAccountCollectionOptions = useMemo(() => [...(bankAccounts ?? []), ...(otherCurrentAssetAccounts ?? [])], [bankAccounts, otherCurrentAssetAccounts]);

const isSyncReimbursedSwitchOn = !!collectionAccountID;
const selectedAccount = '92345'; // TODO: use fake selected account temporarily.

const selectedQboAccountName = useMemo(() => qboAccountOptions?.find(({id}) => id === reimbursementAccountID)?.name, [qboAccountOptions, reimbursementAccountID]);
const selectedInvoiceCollectionAccountName = useMemo(
() => invoiceAccountCollectionOptions?.find(({id}) => id === collectionAccountID)?.name,
[invoiceAccountCollectionOptions, collectionAccountID],
);

const syncReimbursedSubMenuItems = () => (
<View style={[styles.mt3]}>
<OfflineWithFeedback pendingAction={pendingFields?.reimbursementAccountID}>
<MenuItemWithTopDescription
shouldShowRightIcon
title={selectedQboAccountName}
description={translate('workspace.qbo.advancedConfig.qboBillPaymentAccount')}
wrapperStyle={[styles.sectionMenuItemTopDescription]}
onPress={waitForNavigate(() => Navigation.navigate(ROUTES.WORKSPACE_ACCOUNTING_QUICKBOOKS_ONLINE_ACCOUNT_SELECTOR.getRoute(policyID)))}
error={errorFields?.reimbursementAccountID ? translate('common.genericErrorMessage') : undefined}
brickRoadIndicator={errorFields?.reimbursementAccountID ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
/>
</OfflineWithFeedback>

<OfflineWithFeedback pendingAction={pendingFields?.collectionAccountID}>
<MenuItemWithTopDescription
shouldShowRightIcon
title={selectedInvoiceCollectionAccountName}
description={translate('workspace.qbo.advancedConfig.qboInvoiceCollectionAccount')}
wrapperStyle={[styles.sectionMenuItemTopDescription]}
onPress={waitForNavigate(() => Navigation.navigate(ROUTES.WORKSPACE_ACCOUNTING_QUICKBOOKS_ONLINE_INVOICE_ACCOUNT_SELECTOR.getRoute(policyID)))}
error={errorFields?.collectionAccountID ? translate('common.genericErrorMessage') : undefined}
brickRoadIndicator={errorFields?.collectionAccountID ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
/>
</OfflineWithFeedback>
</View>
);

const qboToggleSettingItems: ToggleSettingOptionRowProps[] = [
{
Expand All @@ -47,6 +83,7 @@ function QuickbooksAdvancedPage({policy}: WithPolicyProps) {
pendingAction: pendingFields?.autoSync,
errors: ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICK_BOOKS_CONFIG.AUTO_SYNC),
onCloseError: () => Policy.clearQBOErrorField(policyID, CONST.QUICK_BOOKS_CONFIG.AUTO_SYNC),
wrapperStyle: styles.mv3,
},
{
title: translate('workspace.qbo.advancedConfig.inviteEmployees'),
Expand All @@ -56,6 +93,7 @@ function QuickbooksAdvancedPage({policy}: WithPolicyProps) {
pendingAction: pendingFields?.syncPeople,
errors: ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICK_BOOKS_CONFIG.SYNCE_PEOPLE),
onCloseError: () => Policy.clearQBOErrorField(policyID, CONST.QUICK_BOOKS_CONFIG.SYNCE_PEOPLE),
wrapperStyle: styles.mv3,
},
{
title: translate('workspace.qbo.advancedConfig.createEntities'),
Expand All @@ -65,6 +103,24 @@ function QuickbooksAdvancedPage({policy}: WithPolicyProps) {
pendingAction: pendingFields?.autoCreateVendor,
errors: ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICK_BOOKS_CONFIG.AUTO_CREATE_VENDOR),
onCloseError: () => Policy.clearQBOErrorField(policyID, CONST.QUICK_BOOKS_CONFIG.AUTO_CREATE_VENDOR),
wrapperStyle: styles.mv3,
},
{
title: translate('workspace.qbo.advancedConfig.reimbursedReports'),
subtitle: translate('workspace.qbo.advancedConfig.reimbursedReportsDescription'),
isActive: isSyncReimbursedSwitchOn,
onToggle: () =>
Connections.updatePolicyConnectionConfig(
policyID,
CONST.POLICY.CONNECTIONS.NAME.QBO,
CONST.QUICK_BOOKS_CONFIG.COLLECTION_ACCOUNT_ID,
isSyncReimbursedSwitchOn ? '' : [...qboAccountOptions, ...invoiceAccountCollectionOptions][0].id,
),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@teneeto Shouldn't this be based on the invoiceAccountCollectionOptions only? This switch will set a collect account and qboAccountOptions may not have valid options (e.g. credit cards)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@s77rt we can look into this further, we were looking at a situation where qboAccountOptions does not have options but invoiceAccountCollectionOptions does have - it means the switch won't toggle on simply because qbaAccountOptions is missing options.

I'm sure this isn't perfect - I can't test in real-time either. I have limitations in seeing exactly what happens.

pendingAction: pendingFields?.collectionAccountID,
errors: ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICK_BOOKS_CONFIG.COLLECTION_ACCOUNT_ID),
onCloseError: () => Policy.clearQBOErrorField(policyID, CONST.QUICK_BOOKS_CONFIG.COLLECTION_ACCOUNT_ID),
subMenuItems: syncReimbursedSubMenuItems(),
wrapperStyle: styles.mv3,
},
];

Expand All @@ -91,79 +147,13 @@ function QuickbooksAdvancedPage({policy}: WithPolicyProps) {
title={item.title}
subtitle={item.subtitle}
shouldPlaceSubtitleBelowSwitch
wrapperStyle={styles.mv3}
wrapperStyle={item.wrapperStyle}
isActive={item.isActive}
onToggle={item.onToggle}
pendingAction={item.pendingAction}
subMenuItems={item.subMenuItems}
/>
))}

<View style={styles.mv3}>
<SpacerView
shouldShow
style={[styles.chatItemComposeBoxColor]}
/>
</View>

<ToggleSettingOptionRow
title={translate('workspace.qbo.advancedConfig.reimbursedReports')}
errors={ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICK_BOOKS_CONFIG.COLLECTION_ACCOUNT_ID)}
onCloseError={() => Policy.clearQBOErrorField(policyID, CONST.QUICK_BOOKS_CONFIG.COLLECTION_ACCOUNT_ID)}
subtitle={translate('workspace.qbo.advancedConfig.reimbursedReportsDescription')}
shouldPlaceSubtitleBelowSwitch
wrapperStyle={styles.mv3}
pendingAction={pendingFields?.collectionAccountID}
isActive={isSyncReimbursedSwitchOn}
onToggle={() =>
Connections.updatePolicyConnectionConfig(
policyID,
CONST.POLICY.CONNECTIONS.NAME.QBO,
CONST.QUICK_BOOKS_CONFIG.COLLECTION_ACCOUNT_ID,
isSyncReimbursedSwitchOn ? '' : selectedAccount,
)
}
/>

{!!collectionAccountID && (
<>
<OfflineWithFeedback pendingAction={pendingFields?.reimbursementAccountID}>
<MenuItemWithTopDescription
shouldShowRightIcon
title="Croissant Co Payroll Account" // TODO: set to the current selected value
description={translate('workspace.qbo.advancedConfig.qboAccount')}
wrapperStyle={[styles.sectionMenuItemTopDescription]}
onPress={waitForNavigate(() => Navigation.navigate(ROUTES.WORKSPACE_ACCOUNTING_QUICKBOOKS_ONLINE_ACCOUNT_SELECTOR.getRoute(policyID)))}
error={errorFields?.reimbursementAccountID ? translate('common.genericErrorMessage') : undefined}
brickRoadIndicator={errorFields?.reimbursementAccountID ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
/>
</OfflineWithFeedback>

<View style={styles.mv3}>
<SpacerView
shouldShow
style={[styles.chatItemComposeBoxColor]}
/>
</View>

<OfflineWithFeedback pendingAction={pendingFields?.collectionAccountID}>
<MenuItem
title={translate('workspace.qbo.advancedConfig.collectionAccount')}
description={translate('workspace.qbo.advancedConfig.collectionAccountDescription')}
shouldShowBasicTitle
wrapperStyle={[styles.sectionMenuItemTopDescription]}
interactive={false}
/>
<MenuItemWithTopDescription
title="Croissant Co Money in Clearing" // TODO: set to the current selected value
shouldShowRightIcon
wrapperStyle={[styles.sectionMenuItemTopDescription]}
onPress={waitForNavigate(() => Navigation.navigate(ROUTES.WORKSPACE_ACCOUNTING_QUICKBOOKS_ONLINE_INVOICE_ACCOUNT_SELECTOR.getRoute(policyID)))}
error={errorFields?.collectionAccountID ? translate('common.genericErrorMessage') : undefined}
brickRoadIndicator={errorFields?.collectionAccountID ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
/>
</OfflineWithFeedback>
</>
)}
</ScrollView>
</ScreenWrapper>
</FeatureEnabledAccessOrNotFoundWrapper>
Expand All @@ -174,4 +164,4 @@ function QuickbooksAdvancedPage({policy}: WithPolicyProps) {

QuickbooksAdvancedPage.displayName = 'QuickbooksAdvancedPage';

export default withPolicy(QuickbooksAdvancedPage);
export default withPolicyConnections(QuickbooksAdvancedPage);
Loading
Loading