Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
fca6165
add setFeedStatementPeriodEndDate (wip)
s77rt Jul 18, 2025
4e4e37f
simplify WorkspaceCompanyCardStatementCloseDateSelectionList state
s77rt Jul 18, 2025
2091cf5
rename SetFeedStatementPeriodEndDate to SetFeedStatementEndDay
s77rt Jul 18, 2025
3879318
lint
s77rt Jul 18, 2025
d3b9094
update type
s77rt Jul 18, 2025
2e84c3a
ts
s77rt Jul 18, 2025
c17cbe6
update setFeedStatementEndDay
s77rt Jul 18, 2025
4399910
call SetFeedStatementEndDay
s77rt Jul 18, 2025
13e04ab
pass default statement date
s77rt Jul 18, 2025
c649b21
added offline and error feedback
s77rt Jul 18, 2025
5f1ba06
add offline and error feedback to WorkspaceCompanyCardStatementCloseD…
s77rt Jul 18, 2025
63e75de
lint
s77rt Jul 18, 2025
9066c8f
rename api param to statementEndDay
s77rt Jul 19, 2025
cdf10d7
Merge branch 'main' into statement-close-date-be
s77rt Jul 21, 2025
0bea3bf
rename to SetFeedStatementPeriodEndDay
s77rt Jul 21, 2025
d9dedf2
rename param
s77rt Jul 21, 2025
d8be3a3
change error position
s77rt Jul 21, 2025
bfb3328
pass statementPeriodEndDay to ImportPlaidAccounts
s77rt Jul 21, 2025
afc5e09
remove dev lock in plaid step and always redirect to statement step
s77rt Jul 21, 2025
89898d5
Pass statementPeriodEndDay to RequestFeedSetup
s77rt Jul 21, 2025
df67ced
optimistically set statementPeriodEndDay
s77rt Jul 21, 2025
629dc2f
lint
s77rt Jul 21, 2025
e9b964b
remove unnecessary param
s77rt Jul 21, 2025
57fe52e
add statement dev lock for existing card feeds
s77rt Jul 21, 2025
1b424a7
add statement dev lock for new direct-with-plaid card feeds
s77rt Jul 21, 2025
de7d6f8
add statement dev lock for new commercial card feeds
s77rt Jul 21, 2025
347643d
empty lines for readability
s77rt Jul 21, 2025
ce3d3d3
Merge branch 'main' into statement-close-date-be
s77rt Jul 23, 2025
ab6c63f
revert the one-state usage and use two states again in CompanyCardSta…
s77rt Jul 24, 2025
453e2be
correct param file name
s77rt Jul 24, 2025
766a761
update API params
s77rt Jul 24, 2025
9acb5e4
update addNewCompanyCardsFeed calls
s77rt Jul 24, 2025
a6f8dd7
update importPlaidAccounts calls
s77rt Jul 24, 2025
02f28f3
update setFeedStatementPeriodEndDay calls
s77rt Jul 24, 2025
c4a5d1c
update statement display value
s77rt Jul 24, 2025
5322ce2
update error and pending fields values
s77rt Jul 24, 2025
f7d7dd4
update statementPeriodEnd values
s77rt Jul 24, 2025
ac6eaba
fix clear error fields
s77rt Jul 24, 2025
a7a1761
lint
s77rt Jul 24, 2025
5e312a6
remove statementPeriodEnd from card feed data
s77rt Jul 24, 2025
70d95c9
update api commands to use only statementPeriodEndDay in onyx updates
s77rt Jul 24, 2025
207d5ad
update error and pending fields
s77rt Jul 24, 2025
55405d7
update display value logic
s77rt Jul 24, 2025
cdd04cc
don't call api if value didn't change
s77rt Jul 24, 2025
e1f9856
wrap submit in useCallback
s77rt Jul 27, 2025
ecd4993
Merge branch 'main' into statement-close-date-be
s77rt Jul 30, 2025
b07f3f3
add backTo param to WorkspaceCompanyCardStatementCloseDatePageProps
s77rt Jul 30, 2025
5a2ab05
redirect user to statement period page after a direct feed is added
s77rt Jul 30, 2025
6cd1223
Merge branch 'main' into statement-close-date-be
s77rt Jul 30, 2025
d4f8fb6
Merge branch 'main' into statement-close-date-be
s77rt Aug 4, 2025
87b3311
lint
s77rt Aug 4, 2025
4090653
remove backTo param from WorkspaceCompanyCardStatementCloseDatePage
s77rt Aug 5, 2025
56fd68c
close RHP before navigating to statement close date page
s77rt Aug 5, 2025
8ba52ad
remove dev lock of statement close date page
s77rt Aug 5, 2025
5f7cdd6
Merge branch 'main' into statement-close-date-be
s77rt Aug 5, 2025
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
6 changes: 3 additions & 3 deletions src/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3283,9 +3283,9 @@ const CONST = {
ALLOW: 'personal',
},
STATEMENT_CLOSE_DATE: {
LAST_DAY_OF_MONTH: 'lastDayOfMonth',
LAST_BUSINESS_DAY_OF_MONTH: 'lastBusinessDayOfMonth',
CUSTOM_DAY_OF_MONTH: 'customDayOfMonth',
LAST_DAY_OF_MONTH: 'LAST_DAY_OF_MONTH',
LAST_BUSINESS_DAY_OF_MONTH: 'LAST_BUSINESS_DAY_OF_MONTH',
CUSTOM_DAY_OF_MONTH: 'CUSTOM_DAY_OF_MONTH',
},
CARD_LIST_THRESHOLD: 8,
DEFAULT_EXPORT_TYPE: 'default',
Expand Down
6 changes: 4 additions & 2 deletions src/hooks/useImportPlaidAccounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ export default function useImportPlaidAccounts(policyID?: string) {
const plaidFeedName = addNewCard?.data?.plaidConnectedFeedName ?? assignCard?.data?.plaidConnectedFeedName;
const plaidAccounts = addNewCard?.data?.plaidAccounts ?? assignCard?.data?.plaidAccounts;
const country = addNewCard?.data?.selectedCountry;
const statementPeriodEnd = addNewCard?.data?.statementPeriodEnd;
const statementPeriodEndDay = addNewCard?.data?.statementPeriodEndDay;

return useCallback(() => {
if (!policyID || !plaidToken || !plaidFeed || !plaidFeedName || !country || !plaidAccounts?.length) {
return;
}
importPlaidAccounts(plaidToken, plaidFeed, plaidFeedName, country, getDomainNameForPolicy(policyID), JSON.stringify(plaidAccounts));
}, [country, plaidAccounts, plaidFeed, plaidFeedName, plaidToken, policyID]);
importPlaidAccounts(plaidToken, plaidFeed, plaidFeedName, country, getDomainNameForPolicy(policyID), JSON.stringify(plaidAccounts), statementPeriodEnd, statementPeriodEndDay);
}, [statementPeriodEnd, statementPeriodEndDay, country, plaidAccounts, plaidFeed, plaidFeedName, plaidToken, policyID]);
}
4 changes: 4 additions & 0 deletions src/libs/API/parameters/ImportPlaidAccountsParams.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import type {StatementPeriodEnd, StatementPeriodEndDay} from '@src/types/onyx/CardFeeds';

type ImportPlaidAccountsParams = {
publicToken: string;
feed: string;
feedName: string;
country: string;
domainName: string;
plaidAccounts: string;
statementPeriodEnd?: StatementPeriodEnd;
statementPeriodEndDay?: StatementPeriodEndDay;
};

export default ImportPlaidAccountsParams;
4 changes: 4 additions & 0 deletions src/libs/API/parameters/RequestFeedSetupParams.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import type {StatementPeriodEnd, StatementPeriodEndDay} from '@src/types/onyx/CardFeeds';

type RequestFeedSetupParams = {
authToken: string;
policyID: string;
feedDetails: string;
feedType: string;
statementPeriodEnd?: StatementPeriodEnd;
statementPeriodEndDay?: StatementPeriodEndDay;
};

export default RequestFeedSetupParams;
12 changes: 12 additions & 0 deletions src/libs/API/parameters/SetFeedStatementPeriodEndDayParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type {StatementPeriodEnd, StatementPeriodEndDay} from '@src/types/onyx/CardFeeds';

type SetFeedStatementPeriodEndDayParams = {
authToken: string | null | undefined;
policyID: string;
bankName: string;
domainAccountID: number;
statementPeriodEnd: StatementPeriodEnd | undefined;
statementPeriodEndDay: StatementPeriodEndDay | undefined;
};

export default SetFeedStatementPeriodEndDayParams;
1 change: 1 addition & 0 deletions src/libs/API/parameters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ export type {default as DeleteCompanyCardFeed} from './DeleteCompanyCardFeed';
export type {default as SetCompanyCardTransactionLiability} from './SetCompanyCardTransactionLiability';
export type {default as OpenPolicyCompanyCardsFeedParams} from './OpenPolicyCompanyCardsFeedParams';
export type {default as OpenPolicyAddCardFeedPageParams} from './OpenPolicyAddCardFeedPageParams';
export type {default as SetFeedStatementPeriodEndDayParams} from './SetFeedStatementPeriodEndDayParams';
export type {default as AssignCompanyCardParams} from './AssignCompanyCardParams';
export type {default as UnassignCompanyCard} from './UnassignCompanyCard';
export type {default as UpdateCompanyCard} from './UpdateCompanyCard';
Expand Down
2 changes: 2 additions & 0 deletions src/libs/API/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,7 @@ const WRITE_COMMANDS = {
DELETE_COMPANY_CARD_FEED: 'RemoveFeed',
SET_COMPANY_CARD_TRANSACTION_LIABILITY: 'SetFeedTransactionLiability',
OPEN_POLICY_ADD_CARD_FEED_PAGE: 'OpenPolicyAddCardFeedPage',
SET_FEED_STATEMENT_PERIOD_END_DAY: 'SetFeedStatementPeriodEndDay',
ASSIGN_COMPANY_CARD: 'AssignCard',
UNASSIGN_COMPANY_CARD: 'UnassignCard',
UPDATE_COMPANY_CARD: 'SyncCard',
Expand Down Expand Up @@ -562,6 +563,7 @@ type WriteCommandParameters = {
[WRITE_COMMANDS.SET_CARD_EXPORT_ACCOUNT]: Parameters.SetCompanyCardExportAccountParams;
[WRITE_COMMANDS.SET_COMPANY_CARD_TRANSACTION_LIABILITY]: Parameters.SetCompanyCardTransactionLiability;
[WRITE_COMMANDS.OPEN_POLICY_ADD_CARD_FEED_PAGE]: Parameters.OpenPolicyAddCardFeedPageParams;
[WRITE_COMMANDS.SET_FEED_STATEMENT_PERIOD_END_DAY]: Parameters.SetFeedStatementPeriodEndDayParams;
[WRITE_COMMANDS.VERIFY_IDENTITY]: Parameters.VerifyIdentityParams;
[WRITE_COMMANDS.ACCEPT_WALLET_TERMS]: Parameters.AcceptWalletTermsParams;
[WRITE_COMMANDS.ANSWER_QUESTIONS_FOR_WALLET]: Parameters.AnswerQuestionsForWalletParams;
Expand Down
120 changes: 116 additions & 4 deletions src/libs/actions/CompanyCards.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type {OnyxEntry, OnyxUpdate} from 'react-native-onyx';
import type {NullishDeep, OnyxEntry, OnyxUpdate} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
import * as API from '@libs/API';
import type {
Expand All @@ -8,6 +8,7 @@ import type {
OpenPolicyExpensifyCardsPageParams,
RequestFeedSetupParams,
SetCompanyCardExportAccountParams,
SetFeedStatementPeriodEndDayParams,
UpdateCompanyCardNameParams,
} from '@libs/API/parameters';
import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
Expand All @@ -21,7 +22,7 @@ import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Card, CardFeeds} from '@src/types/onyx';
import type {AssignCard, AssignCardData} from '@src/types/onyx/AssignCard';
import type {AddNewCardFeedData, AddNewCardFeedStep, CardFeedDetails, CompanyCardFeed} from '@src/types/onyx/CardFeeds';
import type {AddNewCardFeedData, AddNewCardFeedStep, CardFeedData, CardFeedDetails, CompanyCardFeed, StatementPeriodEnd, StatementPeriodEndDay} from '@src/types/onyx/CardFeeds';
import type {OnyxData} from '@src/types/onyx/Request';

type AddNewCompanyCardFlowData = {
Expand All @@ -47,7 +48,7 @@ function clearAssignCardStepAndData() {
Onyx.set(ONYXKEYS.ASSIGN_CARD, {});
}

function setAddNewCompanyCardStepAndData({data, isEditing, step}: AddNewCompanyCardFlowData) {
function setAddNewCompanyCardStepAndData({data, isEditing, step}: NullishDeep<AddNewCompanyCardFlowData>) {
Onyx.merge(ONYXKEYS.ADD_NEW_COMPANY_CARD, {data, isEditing, currentStep: step});
}

Expand All @@ -58,7 +59,15 @@ function clearAddNewCardFlow() {
});
}

function addNewCompanyCardsFeed(policyID: string | undefined, cardFeed: CompanyCardFeed, feedDetails: CardFeedDetails, cardFeeds: OnyxEntry<CardFeeds>, lastSelectedFeed?: CompanyCardFeed) {
function addNewCompanyCardsFeed(
policyID: string | undefined,
cardFeed: CompanyCardFeed,
feedDetails: CardFeedDetails,
cardFeeds: OnyxEntry<CardFeeds>,
statementPeriodEnd: StatementPeriodEnd | undefined,
statementPeriodEndDay: StatementPeriodEndDay | undefined,
lastSelectedFeed?: CompanyCardFeed,
) {
const authToken = NetworkStore.getAuthToken();
const workspaceAccountID = PolicyUtils.getWorkspaceAccountID(policyID);

Expand All @@ -82,6 +91,7 @@ function addNewCompanyCardsFeed(policyID: string | undefined, cardFeed: CompanyC
settings: {
companyCards: {
[feedType]: {
statementPeriodEndDay: statementPeriodEndDay ?? statementPeriodEnd ?? null,
errors: null,
},
},
Expand Down Expand Up @@ -134,6 +144,8 @@ function addNewCompanyCardsFeed(policyID: string | undefined, cardFeed: CompanyC
feedDetails: Object.entries(feedDetails)
.map(([key, value]) => `${key}: ${value}`)
.join(', '),
statementPeriodEnd,
statementPeriodEndDay,
};

API.write(WRITE_COMMANDS.REQUEST_FEED_SETUP, parameters, {optimisticData, failureData, successData, finallyData});
Expand Down Expand Up @@ -811,6 +823,104 @@ function openPolicyAddCardFeedPage(policyID: string | undefined) {
API.write(WRITE_COMMANDS.OPEN_POLICY_ADD_CARD_FEED_PAGE, parameters);
}

function setFeedStatementPeriodEndDay(
policyID: string,
bankName: string,
domainAccountID: number,
newStatementPeriodEnd: StatementPeriodEnd | undefined,
newStatementPeriodEndDay: StatementPeriodEndDay | undefined,
oldStatementPeriodEndDay: StatementPeriodEnd | StatementPeriodEndDay | undefined,
) {
const authToken = NetworkStore.getAuthToken();

const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${domainAccountID}`,
value: {
settings: {
companyCards: {
[bankName]: {
statementPeriodEndDay: newStatementPeriodEndDay ?? newStatementPeriodEnd ?? null,
pendingFields: {
statementPeriodEndDay: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
},
errorFields: {
statementPeriodEndDay: null,
},
},
},
},
},
},
];

const successData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${domainAccountID}`,
value: {
settings: {
companyCards: {
[bankName]: {
pendingFields: {
statementPeriodEndDay: null,
},
},
},
},
},
},
];

const failureData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${domainAccountID}`,
value: {
settings: {
companyCards: {
[bankName]: {
statementPeriodEndDay: oldStatementPeriodEndDay ?? null,
pendingFields: {
statementPeriodEndDay: null,
},
errorFields: {
statementPeriodEndDay: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'),
},
},
},
},
},
},
];

const parameters: SetFeedStatementPeriodEndDayParams = {
authToken,
policyID,
bankName,
domainAccountID,
statementPeriodEnd: newStatementPeriodEnd,
statementPeriodEndDay: newStatementPeriodEndDay,
};

API.write(WRITE_COMMANDS.SET_FEED_STATEMENT_PERIOD_END_DAY, parameters, {optimisticData, successData, failureData});
}

function clearErrorField(bankName: string, domainAccountID: number, fieldName: keyof CardFeedData) {
Onyx.merge(`${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${domainAccountID}`, {
settings: {
companyCards: {
[bankName]: {
errorFields: {
[fieldName]: null,
},
},
},
},
});
}

export {
setWorkspaceCompanyCardFeedName,
deleteWorkspaceCompanyCardFeed,
Expand All @@ -831,4 +941,6 @@ export {
openAssignFeedCardPage,
openPolicyAddCardFeedPage,
setTransactionStartDate,
setFeedStatementPeriodEndDay,
clearErrorField,
};
14 changes: 13 additions & 1 deletion src/libs/actions/Plaid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
import getPlaidLinkTokenParameters from '@libs/getPlaidLinkTokenParameters';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {StatementPeriodEnd, StatementPeriodEndDay} from '@src/types/onyx/CardFeeds';

/**
* Gets the Plaid Link token used to initialize the Plaid SDK
Expand Down Expand Up @@ -116,14 +117,25 @@ function openPlaidBankAccountSelector(publicToken: string, bankName: string, all
});
}

function importPlaidAccounts(publicToken: string, feed: string, feedName: string, country: string, domainName: string, plaidAccounts: string) {
function importPlaidAccounts(
publicToken: string,
feed: string,
feedName: string,
country: string,
domainName: string,
plaidAccounts: string,
statementPeriodEnd: StatementPeriodEnd | undefined,
statementPeriodEndDay: StatementPeriodEndDay | undefined,
) {
const parameters: ImportPlaidAccountsParams = {
publicToken,
feed,
feedName,
country,
domainName,
plaidAccounts,
statementPeriodEnd,
statementPeriodEndDay,
};

API.write(WRITE_COMMANDS.IMPORT_PLAID_ACCOUNTS, parameters);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,15 @@ function BankConnection({policyID: policyIDFromProps, feed, route}: BankConnecti
if (newFeed) {
updateSelectedFeed(newFeed, policyID);
}
Navigation.goBack(ROUTES.WORKSPACE_COMPANY_CARDS.getRoute(policyID));

// Direct feeds (except those added via Plaid) are created with default statement period end date.
// Redirect the user to set a custom date.
if (policyID && !isPlaid) {
Navigation.closeRHPFlow();
Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_SETTINGS_STATEMENT_CLOSE_DATE.getRoute(policyID));
} else {
Navigation.goBack(ROUTES.WORKSPACE_COMPANY_CARDS.getRoute(policyID));
}
}
if (isPlaid) {
onImportPlaidAccounts();
Expand Down
12 changes: 10 additions & 2 deletions src/pages/workspace/companyCards/BankConnection/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,16 @@ function BankConnection({policyID: policyIDFromProps, feed, route}: BankConnecti
if (newFeed) {
updateSelectedFeed(newFeed, policyID);
}
Navigation.closeRHPFlow();
Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS.getRoute(policyID), {forceReplace: true});

// Direct feeds (except those added via Plaid) are created with default statement period end date.
// Redirect the user to set a custom date.
if (policyID && !isPlaid) {
Navigation.closeRHPFlow();
Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_SETTINGS_STATEMENT_CLOSE_DATE.getRoute(policyID));
} else {
Navigation.closeRHPFlow();
Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS.getRoute(policyID), {forceReplace: true});
}
return;
}
if (!shouldBlockWindowOpen) {
Expand Down
Loading
Loading