Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ function resetNonUSDBankAccount(policyID: string | undefined, achAccount: OnyxEn
const isPreviousLastUsedPaymentMethodVBBA = lastUsedPaymentMethod?.lastUsed?.name === CONST.IOU.PAYMENT_TYPE.VBBA;

const onyxData: OnyxData<
typeof ONYXKEYS.NVP_LAST_PAYMENT_METHOD | typeof ONYXKEYS.REIMBURSEMENT_ACCOUNT | typeof ONYXKEYS.COLLECTION.POLICY | typeof ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT
| typeof ONYXKEYS.NVP_LAST_PAYMENT_METHOD
| typeof ONYXKEYS.REIMBURSEMENT_ACCOUNT
| typeof ONYXKEYS.COLLECTION.POLICY
| typeof ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT
| typeof ONYXKEYS.BANK_ACCOUNT_LIST
> = {
optimisticData: [
{
Expand All @@ -51,6 +55,11 @@ function resetNonUSDBankAccount(policyID: string | undefined, achAccount: OnyxEn
achData: null,
},
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: ONYXKEYS.BANK_ACCOUNT_LIST,
value: {[bankAccountID]: {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE}},
},
],
successData: [
{
Expand All @@ -63,13 +72,23 @@ function resetNonUSDBankAccount(policyID: string | undefined, achAccount: OnyxEn
key: ONYXKEYS.REIMBURSEMENT_ACCOUNT,
value: CONST.REIMBURSEMENT_ACCOUNT.DEFAULT_DATA,
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: ONYXKEYS.BANK_ACCOUNT_LIST,
value: {[bankAccountID]: null},
},
],
failureData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: ONYXKEYS.REIMBURSEMENT_ACCOUNT,
value: {isLoading: false, pendingAction: null},
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: ONYXKEYS.BANK_ACCOUNT_LIST,
value: {[bankAccountID]: {pendingAction: null}},
},
],
};

Expand Down
16 changes: 16 additions & 0 deletions src/libs/actions/ReimbursementAccount/resetUSDBankAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ function resetUSDBankAccount(
| typeof ONYXKEYS.RAM_ONLY_PLAID_LINK_TOKEN
| typeof ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT
| typeof ONYXKEYS.NVP_LAST_PAYMENT_METHOD
| typeof ONYXKEYS.BANK_ACCOUNT_LIST
> = {
optimisticData: [
{
Expand All @@ -57,6 +58,11 @@ function resetUSDBankAccount(
achAccount: null,
},
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: ONYXKEYS.BANK_ACCOUNT_LIST,
value: {[bankAccountID]: {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE}},
},
],
successData: [
{
Expand Down Expand Up @@ -128,6 +134,11 @@ function resetUSDBankAccount(
[INPUT_IDS.AMOUNT3]: '',
},
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: ONYXKEYS.BANK_ACCOUNT_LIST,
value: {[bankAccountID]: null},
},
],
failureData: [
{
Expand All @@ -142,6 +153,11 @@ function resetUSDBankAccount(
achAccount,
},
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: ONYXKEYS.BANK_ACCOUNT_LIST,
value: {[bankAccountID]: {pendingAction: null}},
},
],
};

Expand Down
8 changes: 6 additions & 2 deletions src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,8 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
const isBusinessBankAccountLocked = state === CONST.BANK_ACCOUNT.STATE.LOCKED;

const shouldShowBankAccount = (!!isBankAccountFullySetup || !!bankAccountConnectedToWorkspace) && policy?.reimbursementChoice !== CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_NO;
const bankAccountPendingAction = bankAccountConnectedToWorkspace?.pendingAction;
const isBankAccountPendingDelete = bankAccountPendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE;

const bankIcon = getBankIcon({bankName: bankName as BankName, isCard: false, styles});

Expand Down Expand Up @@ -526,7 +528,7 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
subMenuItems: (
<>
{shouldShowBankAccount ? (
<>
<OfflineWithFeedback pendingAction={bankAccountPendingAction}>
<View style={[styles.sectionMenuItemTopDescription, styles.mt5, styles.pb1, styles.pt1]}>
<Text style={[styles.textLabelSupportingNormal, styles.colorMuted]}>{translate('workflowsPayerPage.paymentAccount')}</Text>
</View>
Expand Down Expand Up @@ -561,6 +563,8 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
iconHeight={bankIcon.iconHeight ?? bankIcon.iconSize}
iconWidth={bankIcon.iconWidth ?? bankIcon.iconSize}
iconStyles={bankIcon.iconStyles}
titleStyle={isBankAccountPendingDelete ? styles.offlineFeedbackDeleted : undefined}
descriptionTextStyle={isBankAccountPendingDelete ? styles.offlineFeedbackDeleted : undefined}
disabled={isOffline || !isPolicyAdmin}
badgeText={getBadgeText(accountData?.state)}
sentryLabel={CONST.SENTRY_LABEL.WORKSPACE.WORKFLOWS.BANK_ACCOUNT}
Expand All @@ -572,7 +576,7 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) {
wrapperStyle={[styles.sectionMenuItemTopDescription, styles.mt3, styles.mbn3]}
brickRoadIndicator={hasReimburserError ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined}
/>
</>
</OfflineWithFeedback>
) : (
<MenuItem
title={translate('bankAccount.addBankAccount')}
Expand Down
170 changes: 170 additions & 0 deletions tests/actions/ReimbursementAccountTest.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Onyx from 'react-native-onyx';
import CONST from '@src/CONST';
import IntlStore from '@src/languages/IntlStore';
import resetNonUSDBankAccount from '@src/libs/actions/ReimbursementAccount/resetNonUSDBankAccount';
import resetUSDBankAccount from '@src/libs/actions/ReimbursementAccount/resetUSDBankAccount';
import ONYXKEYS from '@src/ONYXKEYS';
import type {ACHAccount} from '@src/types/onyx/Policy';
Expand Down Expand Up @@ -60,5 +61,174 @@ describe('ReimbursementAccount', () => {
}),
);
});

it('should optimistically mark bank account as pending deletion', async () => {
(fetch as MockFetch)?.pause?.();
const achAccount: ACHAccount = {
bankAccountID,
addressName: 'Test Address',
bankName: 'Test Bank',
reimburser: TEST_EMAIL,
accountNumber: '1234567890',
routingNumber: '123456789',
};
await Onyx.set(ONYXKEYS.BANK_ACCOUNT_LIST, {
[bankAccountID]: {bankCurrency: 'USD', bankCountry: 'US'},
});
await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {achAccount});
resetUSDBankAccount(bankAccountID, session, policyID, achAccount);

await waitForBatchedUpdates();
return new Promise<void>((resolve) => {
const connection = Onyx.connect({
key: ONYXKEYS.BANK_ACCOUNT_LIST,
callback: (bankAccountList) => {
Onyx.disconnect(connection);
expect(bankAccountList?.[bankAccountID]?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE);
resolve();
},
});
});
});

it('should remove bank account from list on success', async () => {
const achAccount: ACHAccount = {
bankAccountID,
addressName: 'Test Address',
bankName: 'Test Bank',
reimburser: TEST_EMAIL,
accountNumber: '1234567890',
routingNumber: '123456789',
};
await Onyx.set(ONYXKEYS.BANK_ACCOUNT_LIST, {
[bankAccountID]: {bankCurrency: 'USD', bankCountry: 'US'},
});
await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {achAccount});
resetUSDBankAccount(bankAccountID, session, policyID, achAccount);

await waitForBatchedUpdates();
return new Promise<void>((resolve) => {
const connection = Onyx.connect({
key: ONYXKEYS.BANK_ACCOUNT_LIST,
callback: (bankAccountList) => {
Onyx.disconnect(connection);
expect(bankAccountList?.[bankAccountID]).toBeUndefined();
resolve();
},
});
});
});
});

describe('resetNonUSDBankAccount', () => {
afterEach(() => {
mockFetch?.resume?.();
});

it('should optimistically mark bank account as pending deletion', async () => {
(fetch as MockFetch)?.pause?.();
const achAccount: ACHAccount = {
bankAccountID,
addressName: 'Test Address',
bankName: 'Test Bank',
reimburser: TEST_EMAIL,
accountNumber: '1234567890',
routingNumber: '123456789',
};
await Onyx.set(ONYXKEYS.BANK_ACCOUNT_LIST, {
[bankAccountID]: {bankCurrency: 'CAD', bankCountry: 'CA'},
});
resetNonUSDBankAccount(policyID, achAccount, bankAccountID);

await waitForBatchedUpdates();
return new Promise<void>((resolve) => {
const connection = Onyx.connect({
key: ONYXKEYS.BANK_ACCOUNT_LIST,
callback: (bankAccountList) => {
Onyx.disconnect(connection);
expect(bankAccountList?.[bankAccountID]?.pendingAction).toBe(CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE);
resolve();
},
});
});
});

it('should remove bank account from list on success', async () => {
const achAccount: ACHAccount = {
bankAccountID,
addressName: 'Test Address',
bankName: 'Test Bank',
reimburser: TEST_EMAIL,
accountNumber: '1234567890',
routingNumber: '123456789',
};
await Onyx.set(ONYXKEYS.BANK_ACCOUNT_LIST, {
[bankAccountID]: {bankCurrency: 'CAD', bankCountry: 'CA'},
});
resetNonUSDBankAccount(policyID, achAccount, bankAccountID);

await waitForBatchedUpdates();
return new Promise<void>((resolve) => {
const connection = Onyx.connect({
key: ONYXKEYS.BANK_ACCOUNT_LIST,
callback: (bankAccountList) => {
Onyx.disconnect(connection);
expect(bankAccountList?.[bankAccountID]).toBeUndefined();
resolve();
},
});
});
});

it('should clear policy achAccount optimistically', async () => {
(fetch as MockFetch)?.pause?.();
const achAccount: ACHAccount = {
bankAccountID,
addressName: 'Test Address',
bankName: 'Test Bank',
reimburser: TEST_EMAIL,
accountNumber: '1234567890',
routingNumber: '123456789',
};
await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {achAccount});
resetNonUSDBankAccount(policyID, achAccount, bankAccountID);

await waitForBatchedUpdates();
return new Promise<void>((resolve) => {
const connection = Onyx.connect({
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
callback: (policy) => {
Onyx.disconnect(connection);
expect(policy?.achAccount).toBeUndefined();
resolve();
},
});
});
});

it('should reset locally without API call when no bankAccountID', async () => {
const achAccount: ACHAccount = {
bankAccountID: 0,
addressName: 'Test Address',
bankName: 'Test Bank',
reimburser: TEST_EMAIL,
accountNumber: '1234567890',
routingNumber: '123456789',
};
await Onyx.set(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`, {achAccount});
resetNonUSDBankAccount(policyID, achAccount);

await waitForBatchedUpdates();
return new Promise<void>((resolve) => {
const connection = Onyx.connect({
key: ONYXKEYS.REIMBURSEMENT_ACCOUNT,
callback: (reimbursementAccount) => {
Onyx.disconnect(connection);
expect(reimbursementAccount).toEqual(CONST.REIMBURSEMENT_ACCOUNT.DEFAULT_DATA);
resolve();
},
});
});
});
});
});
Loading