Skip to content

Commit 921aa0d

Browse files
authored
Merge pull request Expensify#103954 from Expensify/claude-csvFeedDefaultStartDateFromBeginning
Default transaction start date to "From the beginning" for CSV card feeds
2 parents adb2c02 + f989a4f commit 921aa0d

3 files changed

Lines changed: 71 additions & 3 deletions

File tree

‎src/hooks/useAssignCard.ts‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {importPlaidAccounts} from '@libs/actions/Plaid';
2-
import {getCompanyCardFeed, getCompanyFeeds, getDefaultCardName, getPlaidCountry, getPlaidInstitutionId, isCustomFeed, isSelectedFeedExpired} from '@libs/CardUtils';
2+
import {getCompanyCardFeed, getCompanyFeeds, getDefaultCardName, getPlaidCountry, getPlaidInstitutionId, isCSVUploadFeed, isCustomFeed, isSelectedFeedExpired} from '@libs/CardUtils';
33
import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute';
44
import Navigation from '@libs/Navigation/Navigation';
55
import {getDomainNameForPolicy, isDeletedPolicyEmployee} from '@libs/PolicyUtils';
@@ -147,6 +147,14 @@ function useInitialAssignCardStep({policyID, selectedFeed}: UseInitialAssignCard
147147
encryptedCardNumber: cardID,
148148
};
149149

150+
// We assume admins only put the transactions they want in a CSV file, so there's no need to limit by date.
151+
// Import all of them by default.
152+
// Direct feeds keep today as the default because the bank can return months of history.
153+
if (isCSVUploadFeed(selectedFeed)) {
154+
cardToAssign.dateOption = CONST.COMPANY_CARD.TRANSACTION_START_DATE_OPTIONS.FROM_BEGINNING;
155+
cardToAssign.startDate = '';
156+
}
157+
150158
// Refetch plaid card list
151159
if (!isFeedExpired && plaidAccessToken && !hasImportedPlaidAccounts.current) {
152160
const country = feedData?.country ?? '';

‎src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,8 @@ function AssigneeStep({route}: AssigneeStepProps) {
134134
cardToAssign.cardName = assignCard.cardToAssign.cardName;
135135
// Preserve any start date the user already picked based on the saved data rather than `isEditing`.
136136
// `isEditing` is false on the header-back-then-Next round trip, so keying off it here would wipe the
137-
// chosen date. In a fresh flow `startDate`/`dateOption` are undefined, so both helpers still fall back
138-
// to today/CUSTOM.
137+
// chosen date. In a fresh flow `useAssignCard` seeds FROM_BEGINNING for CSV feeds. For other feeds
138+
// `startDate`/`dateOption` are undefined, so both helpers fall back to today/CUSTOM.
139139
cardToAssign.startDate = getCardAssignmentStartDate(true, assignCard?.cardToAssign?.startDate);
140140
cardToAssign.dateOption = getCardAssignmentDateOption(true, assignCard?.cardToAssign?.dateOption);
141141
setAssignCardStepAndData({

‎tests/unit/hooks/useAssignCard.test.ts‎

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,4 +355,64 @@ describe('useAssignCard', () => {
355355
);
356356
});
357357
});
358+
359+
describe('assignCard function - default transaction start date', () => {
360+
it.each([CONST.COMPANY_CARD.FEED_BANK_NAME.CSV, CONST.COMPANY_CARD.FEED_BANK_NAME.CSV_CLASSIC])('should default to "From the beginning" for %s CSV feeds', (feedBankName) => {
361+
// Given a CSV-uploaded feed, where we assume admins only include the transactions they want imported
362+
const csvFeed: CompanyCardFeedWithDomainID = `${feedBankName}#${workspaceAccountID}`;
363+
const csvFeedData: CombinedCardFeeds = {
364+
[csvFeed]: {
365+
liabilityType: 'corporate',
366+
pending: false,
367+
domainID: workspaceAccountID,
368+
customFeedName: 'CSV cards',
369+
feed: feedBankName,
370+
},
371+
};
372+
jest.mocked(useCardFeeds).mockReturnValue([csvFeedData, {status: 'loaded'}, undefined, {}, workspaceAccountID]);
373+
374+
const {result} = renderHook(() =>
375+
useAssignCard({
376+
feedName: csvFeed,
377+
policyID: mockPolicyID,
378+
setShouldShowOfflineModal: mockSetShouldShowOfflineModal,
379+
}),
380+
);
381+
382+
// When the admin starts assigning a card from that feed
383+
result.current.assignCard('CSV card 1234', 'CSV card 1234');
384+
385+
// Then the start date defaults to "From the beginning" so every transaction in the file imports
386+
expect(setAssignCardStepAndData).toHaveBeenCalledWith(
387+
expect.objectContaining({
388+
cardToAssign: expect.objectContaining({
389+
dateOption: CONST.COMPANY_CARD.TRANSACTION_START_DATE_OPTIONS.FROM_BEGINNING,
390+
startDate: '',
391+
}),
392+
}),
393+
);
394+
});
395+
396+
it('should not seed a start date for direct feeds', () => {
397+
// Given a direct bank feed, which can return months of history
398+
jest.mocked(useCardFeeds).mockReturnValue([mockDirectFeedData, {status: 'loaded'}, undefined, {}, workspaceAccountID]);
399+
400+
const {result} = renderHook(() =>
401+
useAssignCard({
402+
feedName: mockDirectFeed,
403+
policyID: mockPolicyID,
404+
setShouldShowOfflineModal: mockSetShouldShowOfflineModal,
405+
}),
406+
);
407+
408+
// When the admin starts assigning a card from that feed
409+
result.current.assignCard('Chase Checking 0000', 'Chase Checking 0000');
410+
411+
// Then no start date is seeded, so the later steps keep defaulting to today
412+
expect(setAssignCardStepAndData).toHaveBeenCalledTimes(1);
413+
const {cardToAssign} = jest.mocked(setAssignCardStepAndData).mock.calls.at(0)?.[0] ?? {};
414+
expect(cardToAssign?.dateOption).toBeUndefined();
415+
expect(cardToAssign?.startDate).toBeUndefined();
416+
});
417+
});
358418
});

0 commit comments

Comments
 (0)