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

[QBD] Export out-of-pocket expenses #50234

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
41dddf2
create draft screens for QuickbooksDesktopOutOfPocket
ZhenjaHorbach Oct 4, 2024
aac8d0f
Merge branch 'main' into qbd-export-settings-quickbooksdesktopoutofpo…
ZhenjaHorbach Oct 4, 2024
74d3252
refactor screens for using qbd
ZhenjaHorbach Oct 4, 2024
023b2fd
fix ts issues
ZhenjaHorbach Oct 4, 2024
23f6476
update routes and connectionName
ZhenjaHorbach Oct 4, 2024
bbfb8f8
fix conflicts
ZhenjaHorbach Oct 7, 2024
bfc726e
remove some TODO
ZhenjaHorbach Oct 7, 2024
29dbcc8
remove some TODO
ZhenjaHorbach Oct 7, 2024
ec48ed7
update translates
ZhenjaHorbach Oct 7, 2024
93b6ddf
fix comments
ZhenjaHorbach Oct 8, 2024
32f2e6f
remove buildOnyxDataForMultipleQuickbooksConfigurations
ZhenjaHorbach Oct 8, 2024
233dd9f
rename QBDNonReimbursableExportAccountType
ZhenjaHorbach Oct 8, 2024
b0653c3
rename QBDNonReimbursableExportAccountType x2
ZhenjaHorbach Oct 8, 2024
669b80f
refactor OutOfPocketExpense screens
ZhenjaHorbach Oct 8, 2024
ef15467
refactor OutOfPocket screens to use reimbursable in upperCase
ZhenjaHorbach Oct 9, 2024
645e310
revert some changes
ZhenjaHorbach Oct 9, 2024
8e52ae0
revert some changes x2
ZhenjaHorbach Oct 9, 2024
b988e8f
Merge branch 'main' into qbd-export-settings-quickbooksdesktopoutofpo…
ZhenjaHorbach Oct 9, 2024
c3caf8e
fix comments
ZhenjaHorbach Oct 9, 2024
069de16
update translates and add some comments
ZhenjaHorbach Oct 9, 2024
0f63a28
update translates and add some comments x2
ZhenjaHorbach Oct 9, 2024
5682001
fix conflicts
ZhenjaHorbach Oct 9, 2024
e2731ae
add some comments
ZhenjaHorbach Oct 9, 2024
d146101
remove file
ZhenjaHorbach Oct 9, 2024
d6fbacf
return QuickbooksDesktop file
ZhenjaHorbach Oct 9, 2024
212a4d7
update qbd comments
ZhenjaHorbach Oct 9, 2024
cd3cc19
update getAccountingIntegrationData
ZhenjaHorbach Oct 9, 2024
1d7acab
fix conflicts
ZhenjaHorbach Oct 10, 2024
ac951b3
fix comment
ZhenjaHorbach Oct 10, 2024
8078758
update journalEntryAccounts
ZhenjaHorbach Oct 10, 2024
3b2083c
update comments
ZhenjaHorbach Oct 10, 2024
ac2d6e8
add getQBDReimbursableAccounts util
ZhenjaHorbach Oct 10, 2024
9cbda7e
fix bug
ZhenjaHorbach Oct 10, 2024
cd6e9ba
update API for QBD
ZhenjaHorbach Oct 10, 2024
c077bd2
update pendingAction for exportOutOfPocketExpensesCheckToogle
ZhenjaHorbach Oct 10, 2024
0b8b5d6
update code to use new api commands
ZhenjaHorbach Oct 11, 2024
04fbce4
update types
ZhenjaHorbach Oct 11, 2024
f7507be
refactor code
ZhenjaHorbach Oct 11, 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
186 changes: 184 additions & 2 deletions src/libs/actions/connections/QuickbooksDesktop.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,46 @@
import isObject from 'lodash/isObject';
import type {OnyxUpdate} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
import * as API from '@libs/API';
import type {ConnectPolicyToQuickBooksDesktopParams} from '@libs/API/parameters';
import type {ConnectPolicyToQuickBooksDesktopParams, UpdateManyPolicyConnectionConfigurationsParams, UpdatePolicyConnectionConfigParams} from '@libs/API/parameters';
import type UpdateQuickbooksDesktopGenericTypeParams from '@libs/API/parameters/UpdateQuickbooksDesktopGenericTypeParams';
import {SIDE_EFFECT_REQUEST_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
import * as ErrorUtils from '@libs/ErrorUtils';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type * as OnyxCommon from '@src/types/onyx/OnyxCommon';
import type {Connections} from '@src/types/onyx/Policy';
import type {DeepPartial} from './index';

function createPendingFields<TSettingName extends keyof Connections['quickbooksDesktop']['config']['export']>(
settingName: TSettingName,
settingValue: Partial<Connections['quickbooksDesktop']['config']['export'][TSettingName]>,
pendingValue: OnyxCommon.PendingAction,
) {
if (!isObject(settingValue)) {
return {[settingName]: pendingValue};
}

return Object.keys(settingValue).reduce<Record<string, OnyxCommon.PendingAction>>((acc, setting) => {
acc[setting] = pendingValue;
return acc;
}, {});
}

function createErrorFields<TSettingName extends keyof Connections['quickbooksDesktop']['config']['export']>(
settingName: TSettingName,
settingValue: Partial<Connections['quickbooksDesktop']['config']['export'][TSettingName]>,
errorValue: OnyxCommon.Errors | null,
) {
if (!isObject(settingValue)) {
return {[settingName]: errorValue};
}

return Object.keys(settingValue).reduce<OnyxCommon.ErrorFields>((acc, setting) => {
acc[setting] = errorValue;
return acc;
}, {});
}

function buildOnyxDataForQuickbooksConfiguration<TSettingName extends keyof Connections['quickbooksDesktop']['config']>(
policyID: string,
Expand Down Expand Up @@ -87,6 +120,155 @@ function buildOnyxDataForQuickbooksConfiguration<TSettingName extends keyof Conn
};
}

// TODO: [QBD] Should be removed to use the new QBD API
// We use DeepPartial to allow partial updates to the config object
function updateManyExportConnectionConfigs<TConfigUpdate extends DeepPartial<Connections['quickbooksDesktop']['config']['export']>>(
ZhenjaHorbach marked this conversation as resolved.
Show resolved Hide resolved
policyID: string,
configUpdate: TConfigUpdate,
configCurrentData: TConfigUpdate,
) {
const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
connections: {
[CONST.POLICY.CONNECTIONS.NAME.QBD]: {
config: {
export: {
...configUpdate,
},
pendingFields: Object.fromEntries(Object.keys(configUpdate).map((settingName) => [settingName, CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE])),
errorFields: Object.fromEntries(Object.keys(configUpdate).map((settingName) => [settingName, null])),
},
},
},
},
},
];

const failureData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
connections: {
[CONST.POLICY.CONNECTIONS.NAME.QBD]: {
config: {
export: {
...configCurrentData,
},
pendingFields: Object.fromEntries(Object.keys(configUpdate).map((settingName) => [settingName, null])),
errorFields: Object.fromEntries(
Object.keys(configUpdate).map((settingName) => [settingName, ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')]),
),
},
},
},
},
},
];

const successData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
connections: {
[CONST.POLICY.CONNECTIONS.NAME.QBD]: {
config: {
pendingFields: Object.fromEntries(Object.keys(configUpdate).map((settingName) => [settingName, null])),
errorFields: Object.fromEntries(Object.keys(configUpdate).map((settingName) => [settingName, null])),
},
},
},
},
},
];

const parameters: UpdateManyPolicyConnectionConfigurationsParams = {
policyID,
connectionName: CONST.POLICY.CONNECTIONS.NAME.QBD,
configUpdate: JSON.stringify({export: configUpdate}),
idempotencyKey: Object.keys(configUpdate).join(','),
};
API.write(WRITE_COMMANDS.UPDATE_MANY_POLICY_CONNECTION_CONFIGS, parameters, {optimisticData, failureData, successData});
}

// TODO: [QBD] Should be removed to use the new QBD API
function updateExportConnectionConfig<TSettingName extends keyof Connections['quickbooksDesktop']['config']['export']>(
ZhenjaHorbach marked this conversation as resolved.
Show resolved Hide resolved
policyID: string,
settingName: TSettingName,
settingValue: Partial<Connections['quickbooksDesktop']['config']['export'][TSettingName]>,
oldSettingValue?: Partial<Connections['quickbooksDesktop']['config']['export'][TSettingName]>,
) {
const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
connections: {
[CONST.POLICY.CONNECTIONS.NAME.QBD]: {
config: {
export: {
[settingName]: settingValue ?? null,
},
pendingFields: createPendingFields(settingName, settingValue, CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE),
errorFields: createErrorFields(settingName, settingValue, null),
},
},
},
},
},
];

const failureData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
connections: {
[CONST.POLICY.CONNECTIONS.NAME.QBD]: {
config: {
export: {
[settingName]: oldSettingValue ?? null,
},
pendingFields: createPendingFields(settingName, settingValue, null),
errorFields: createErrorFields(settingName, settingValue, ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')),
},
},
},
},
},
];

const successData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
connections: {
[CONST.POLICY.CONNECTIONS.NAME.QBD]: {
config: {
pendingFields: createPendingFields(settingName, settingValue, null),
errorFields: createErrorFields(settingName, settingValue, null),
},
},
},
},
},
];

const parameters: UpdatePolicyConnectionConfigParams = {
policyID,
connectionName: CONST.POLICY.CONNECTIONS.NAME.QBD,
settingName: String('export'),
settingValue: JSON.stringify({[settingName]: settingValue}),
idempotencyKey: String('export'),
};
API.write(WRITE_COMMANDS.UPDATE_POLICY_CONNECTION_CONFIG, parameters, {optimisticData, failureData, successData});
}

function getQuickbooksDesktopCodatSetupLink(policyID: string) {
const params: ConnectPolicyToQuickBooksDesktopParams = {policyID};

Expand All @@ -109,4 +291,4 @@ function updateQuickbooksDesktopMarkChecksToBePrinted<TSettingValue extends Conn
API.write(WRITE_COMMANDS.UPDATE_QUICKBOOKS_DESKTOP_MARK_CHECKS_TO_BE_PRINTED, parameters, onyxData);
}

export {updateQuickbooksDesktopMarkChecksToBePrinted, getQuickbooksDesktopCodatSetupLink};
export {updateQuickbooksDesktopMarkChecksToBePrinted, updateExportConnectionConfig, getQuickbooksDesktopCodatSetupLink, updateManyExportConnectionConfigs};
2 changes: 2 additions & 0 deletions src/libs/actions/connections/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,8 @@ function isConnectionInProgress(connectionSyncProgress: OnyxEntry<PolicyConnecti
);
}

export type {DeepPartial};

export {
removePolicyConnection,
updatePolicyConnectionConfig,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import usePermissions from '@hooks/usePermissions';
import useThemeStyles from '@hooks/useThemeStyles';
import * as Connections from '@libs/actions/connections/index';
import * as QuickbooksDesktop from '@libs/actions/connections/QuickbooksDesktop';
import * as ErrorUtils from '@libs/ErrorUtils';
import * as PolicyUtils from '@libs/PolicyUtils';
import Navigation from '@navigation/Navigation';
Expand Down Expand Up @@ -70,13 +70,7 @@ function QuickbooksDesktopOutOfPocketExpenseAccountSelectPage({policy}: WithPoli
const selectExportAccount = useCallback(
(row: CardListItem) => {
if (row.value.id !== qbdConfig?.export?.reimbursableAccount) {
Connections.updatePolicyConnectionConfig(
policyID,
CONST.POLICY.CONNECTIONS.NAME.QBD,
'export',
{[CONST.QUICKBOOKS_DESKTOP_CONFIG.REIMBURSABLE_ACCOUNT]: row.value.id},
{[CONST.QUICKBOOKS_DESKTOP_CONFIG.REIMBURSABLE_ACCOUNT]: qbdConfig?.export?.reimbursableAccount},
);
QuickbooksDesktop.updateExportConnectionConfig(policyID, CONST.QUICKBOOKS_DESKTOP_CONFIG.REIMBURSABLE_ACCOUNT, row.value.id, qbdConfig?.export?.reimbursableAccount);
}
Navigation.goBack(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_DESKTOP_EXPORT_OUT_OF_POCKET_EXPENSES.getRoute(policyID));
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type {SelectorType} from '@components/SelectionScreen';
import useLocalize from '@hooks/useLocalize';
import usePermissions from '@hooks/usePermissions';
import useThemeStyles from '@hooks/useThemeStyles';
import * as Connections from '@libs/actions/connections';
import * as QuickbooksDesktop from '@libs/actions/connections/QuickbooksDesktop';
import * as ErrorUtils from '@libs/ErrorUtils';
import * as PolicyUtils from '@libs/PolicyUtils';
import Navigation from '@navigation/Navigation';
Expand Down Expand Up @@ -67,20 +67,15 @@ function QuickbooksDesktopOutOfPocketExpenseEntitySelectPage({policy}: WithPolic
const selectExportEntity = useCallback(
(row: MenuItem) => {
if (row.value !== reimbursable) {
Connections.updateManyPolicyConnectionConfigs(
QuickbooksDesktop.updateManyExportConnectionConfigs(
policyID,
CONST.POLICY.CONNECTIONS.NAME.QBD,
{
export: {
[CONST.QUICKBOOKS_DESKTOP_CONFIG.REIMBURSABLE]: row.value,
[CONST.QUICKBOOKS_DESKTOP_CONFIG.REIMBURSABLE_ACCOUNT]: row.accounts.at(0)?.id ?? '',
},
[CONST.QUICKBOOKS_DESKTOP_CONFIG.REIMBURSABLE]: row.value,
[CONST.QUICKBOOKS_DESKTOP_CONFIG.REIMBURSABLE_ACCOUNT]: row.accounts.at(0)?.id ?? '',
},
{
export: {
[CONST.QUICKBOOKS_DESKTOP_CONFIG.REIMBURSABLE]: reimbursable,
[CONST.QUICKBOOKS_DESKTOP_CONFIG.REIMBURSABLE_ACCOUNT]: qbdConfig?.export?.reimbursableAccount,
},
[CONST.QUICKBOOKS_DESKTOP_CONFIG.REIMBURSABLE]: reimbursable,
[CONST.QUICKBOOKS_DESKTOP_CONFIG.REIMBURSABLE_ACCOUNT]: qbdConfig?.export?.reimbursableAccount,
},
);
}
Expand Down
Loading