Skip to content

Commit 04bfa3e

Browse files
authored
Merge pull request Expensify#79960 from dukenv0307/fix/67778-part-6
refactor initMoneyRequest
2 parents 2cf4850 + a25f1d1 commit 04bfa3e

8 files changed

Lines changed: 150 additions & 1 deletion

File tree

src/components/TestDrive/Modal/EmployeeTestDriveModal.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ function EmployeeTestDriveModal() {
4949
const currentUserPersonalDetails = useCurrentUserPersonalDetails();
5050
const personalPolicy = usePersonalPolicy();
5151
const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true});
52+
const [draftTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {canBeMissing: true});
5253
const hasOnlyPersonalPolicies = useMemo(() => hasOnlyPersonalPoliciesUtil(allPolicies), [allPolicies]);
5354

5455
const onBossEmailChange = useCallback((value: string) => {
@@ -85,6 +86,7 @@ function EmployeeTestDriveModal() {
8586
currentDate,
8687
currentUserPersonalDetails,
8788
hasOnlyPersonalPolicies,
89+
draftTransactions,
8890
});
8991

9092
setMoneyRequestReceipt(transactionID, source, filename, true, CONST.TEST_RECEIPT.FILE_TYPE, false, true);

src/libs/actions/IOU/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ type InitMoneyRequestParams = {
286286
lastSelectedDistanceRates?: OnyxEntry<OnyxTypes.LastSelectedDistanceRates>;
287287
currentUserPersonalDetails: CurrentUserPersonalDetails;
288288
hasOnlyPersonalPolicies: boolean;
289+
draftTransactions: OnyxCollection<OnyxTypes.Transaction>;
289290
};
290291

291292
type MoneyRequestInformation = {
@@ -1095,6 +1096,7 @@ function initMoneyRequest({
10951096
lastSelectedDistanceRates,
10961097
currentUserPersonalDetails,
10971098
hasOnlyPersonalPolicies,
1099+
draftTransactions,
10981100
}: InitMoneyRequestParams) {
10991101
// Generate a brand new transactionID
11001102
const newTransactionID = CONST.IOU.OPTIMISTIC_TRANSACTION_ID;
@@ -1105,7 +1107,7 @@ function initMoneyRequest({
11051107
const created = currentDate || format(new Date(), 'yyyy-MM-dd');
11061108

11071109
// We remove draft transactions created during multi scanning if there are some
1108-
removeDraftTransactions(true);
1110+
removeDraftTransactions(true, draftTransactions);
11091111

11101112
// in case we have to re-init money request, but the IOU request type is the same with the old draft transaction,
11111113
// we should keep most of the existing data by using the ONYX MERGE operation

src/pages/Search/SearchPage.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ function SearchPage({route}: SearchPageProps) {
124124
const [activePolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${activePolicyID}`, {canBeMissing: true});
125125
const [personalPolicyID] = useOnyx(ONYXKEYS.PERSONAL_POLICY_ID, {canBeMissing: true});
126126
const [personalPolicy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${personalPolicyID}`, {canBeMissing: true});
127+
const [draftTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {canBeMissing: true});
127128
const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST, {canBeMissing: true});
128129
const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true});
129130
const [integrationsExportTemplates] = useOnyx(ONYXKEYS.NVP_INTEGRATION_SERVER_EXPORT_TEMPLATES, {canBeMissing: true});
@@ -1038,6 +1039,7 @@ function SearchPage({route}: SearchPageProps) {
10381039
currentDate,
10391040
currentUserPersonalDetails,
10401041
hasOnlyPersonalPolicies,
1042+
draftTransactions,
10411043
});
10421044

10431045
const newReceiptFiles: ReceiptFile[] = [];

src/pages/Share/SubmitDetailsPage.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ function SubmitDetailsPage({
8686
const fileName = shouldUsePreValidatedFile ? getFileName(validFilesToUpload?.uri ?? CONST.ATTACHMENT_IMAGE_DEFAULT_NAME) : getFileName(currentAttachment?.content ?? '');
8787
const fileType = shouldUsePreValidatedFile ? (validFilesToUpload?.type ?? CONST.RECEIPT_ALLOWED_FILE_TYPES.JPEG) : (currentAttachment?.mimeType ?? '');
8888
const [hasOnlyPersonalPolicies = false] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true, selector: hasOnlyPersonalPoliciesUtil});
89+
const [draftTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {canBeMissing: true});
8990

9091
useEffect(() => {
9192
if (!errorTitle || !errorMessage) {
@@ -107,7 +108,10 @@ function SubmitDetailsPage({
107108
currentDate,
108109
currentUserPersonalDetails,
109110
hasOnlyPersonalPolicies,
111+
draftTransactions,
110112
});
113+
// The draftTransactions can be changed if users update the expense, so we don't want to re-init the money request
114+
// eslint-disable-next-line react-hooks/exhaustive-deps
111115
}, [reportOrAccountID, policy, personalPolicy, report, parentReport, currentDate, currentUserPersonalDetails, hasOnlyPersonalPolicies]);
112116

113117
const selectedParticipants = unknownUserDetails ? [unknownUserDetails] : getMoneyRequestParticipantsFromReport(report, currentUserPersonalDetails.accountID);

src/pages/inbox/report/ReportActionCompose/useAttachmentUploadValidation.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ function useAttachmentUploadValidation({
5555
const [policyCategories] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policy?.id}`, {canBeMissing: true});
5656
const personalPolicy = usePersonalPolicy();
5757
const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: true});
58+
const [draftTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {canBeMissing: true});
5859
const hasOnlyPersonalPolicies = useMemo(() => hasOnlyPersonalPoliciesUtil(allPolicies), [allPolicies]);
5960

6061
const reportAttachmentsContext = useContext(AttachmentModalContext);
@@ -101,6 +102,7 @@ function useAttachmentUploadValidation({
101102
currentDate,
102103
currentUserPersonalDetails,
103104
hasOnlyPersonalPolicies,
105+
draftTransactions,
104106
});
105107

106108
for (const [index, file] of files.entries()) {

src/pages/iou/request/DistanceRequestStartPage.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ function DistanceRequestStartPage({
5858
const [lastDistanceExpenseType] = useOnyx(ONYXKEYS.NVP_LAST_DISTANCE_EXPENSE_TYPE, {canBeMissing: true});
5959
const isLoadingSelectedTab = isLoadingOnyxValue(selectedTabResult);
6060
const [transaction] = useOnyx(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${getNonEmptyStringOnyxID(route?.params.transactionID)}`, {canBeMissing: true});
61+
const [draftTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {canBeMissing: true});
6162
const [allPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {canBeMissing: false});
6263
const [lastSelectedDistanceRates] = useOnyx(ONYXKEYS.NVP_LAST_SELECTED_DISTANCE_RATES, {canBeMissing: true});
6364
const [currentDate] = useOnyx(ONYXKEYS.CURRENT_DATE, {canBeMissing: true});
@@ -120,6 +121,7 @@ function DistanceRequestStartPage({
120121
lastSelectedDistanceRates,
121122
currentUserPersonalDetails,
122123
hasOnlyPersonalPolicies,
124+
draftTransactions,
123125
});
124126
},
125127
[
@@ -134,6 +136,7 @@ function DistanceRequestStartPage({
134136
lastSelectedDistanceRates,
135137
currentUserPersonalDetails,
136138
hasOnlyPersonalPolicies,
139+
draftTransactions,
137140
],
138141
);
139142

src/pages/iou/request/IOURequestStartPage.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ function IOURequestStartPage({
9090
selector: transactionDraftValuesSelector,
9191
canBeMissing: true,
9292
});
93+
const [draftTransactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_DRAFT, {canBeMissing: true});
9394
const [isMultiScanEnabled, setIsMultiScanEnabled] = useState((optimisticTransactions ?? []).length > 1);
9495
const [currentDate] = useOnyx(ONYXKEYS.CURRENT_DATE, {canBeMissing: true});
9596
const {isOffline} = useNetwork();
@@ -196,6 +197,7 @@ function IOURequestStartPage({
196197
lastSelectedDistanceRates,
197198
currentUserPersonalDetails,
198199
hasOnlyPersonalPolicies,
200+
draftTransactions,
199201
});
200202
},
201203
[
@@ -211,6 +213,7 @@ function IOURequestStartPage({
211213
lastSelectedDistanceRates,
212214
currentUserPersonalDetails,
213215
hasOnlyPersonalPolicies,
216+
draftTransactions,
214217
],
215218
);
216219

tests/actions/IOUTest.ts

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8091,6 +8091,7 @@ describe('actions/IOU', () => {
80918091
currentDate,
80928092
currentUserPersonalDetails,
80938093
hasOnlyPersonalPolicies: false,
8094+
draftTransactions: undefined,
80948095
});
80958096
})
80968097
.then(async () => {
@@ -8113,6 +8114,7 @@ describe('actions/IOU', () => {
81138114
currentDate,
81148115
currentUserPersonalDetails,
81158116
hasOnlyPersonalPolicies: false,
8117+
draftTransactions: undefined,
81168118
});
81178119
})
81188120
.then(async () => {
@@ -8136,6 +8138,7 @@ describe('actions/IOU', () => {
81368138
currentDate,
81378139
currentUserPersonalDetails,
81388140
hasOnlyPersonalPolicies: false,
8141+
draftTransactions: undefined,
81398142
});
81408143
})
81418144
.then(async () => {
@@ -8145,6 +8148,134 @@ describe('actions/IOU', () => {
81458148
});
81468149
});
81478150
});
8151+
8152+
it('should remove non-optimistic draft transactions when draftTransactions is provided', async () => {
8153+
const otherDraftTransactionID = '123456';
8154+
const otherDraftTransaction: Transaction = {
8155+
...createRandomTransaction(1),
8156+
transactionID: otherDraftTransactionID,
8157+
};
8158+
8159+
// Set up an additional draft transaction
8160+
await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${otherDraftTransactionID}`, otherDraftTransaction);
8161+
8162+
const draftTransactions = {
8163+
[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${otherDraftTransactionID}`]: otherDraftTransaction,
8164+
};
8165+
8166+
await waitForBatchedUpdates()
8167+
.then(() => {
8168+
initMoneyRequest({
8169+
reportID: fakeReport.reportID,
8170+
policy: fakePolicy,
8171+
personalPolicy: fakePersonalPolicy,
8172+
isFromGlobalCreate: true,
8173+
newIouRequestType: CONST.IOU.REQUEST_TYPE.MANUAL,
8174+
report: fakeReport,
8175+
parentReport: fakeParentReport,
8176+
currentDate,
8177+
currentUserPersonalDetails,
8178+
hasOnlyPersonalPolicies: false,
8179+
draftTransactions,
8180+
});
8181+
})
8182+
.then(async () => {
8183+
// The other draft transaction should be removed (Onyx returns undefined for removed keys)
8184+
expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${otherDraftTransactionID}`)).toBeUndefined();
8185+
// The optimistic transaction should be created
8186+
expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${CONST.IOU.OPTIMISTIC_TRANSACTION_ID}`)).toStrictEqual(transactionResult);
8187+
});
8188+
});
8189+
8190+
it('should preserve optimistic transaction in draftTransactions while removing others', async () => {
8191+
const otherDraftTransactionID = '789012';
8192+
const otherDraftTransaction: Transaction = {
8193+
...createRandomTransaction(2),
8194+
transactionID: otherDraftTransactionID,
8195+
};
8196+
const existingOptimisticTransaction: Transaction = {
8197+
...createRandomTransaction(3),
8198+
transactionID: CONST.IOU.OPTIMISTIC_TRANSACTION_ID,
8199+
};
8200+
8201+
// Set up both draft transactions
8202+
await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${otherDraftTransactionID}`, otherDraftTransaction);
8203+
await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${CONST.IOU.OPTIMISTIC_TRANSACTION_ID}`, existingOptimisticTransaction);
8204+
8205+
const draftTransactions = {
8206+
[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${otherDraftTransactionID}`]: otherDraftTransaction,
8207+
[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${CONST.IOU.OPTIMISTIC_TRANSACTION_ID}`]: existingOptimisticTransaction,
8208+
};
8209+
8210+
await waitForBatchedUpdates()
8211+
.then(() => {
8212+
initMoneyRequest({
8213+
reportID: fakeReport.reportID,
8214+
policy: fakePolicy,
8215+
personalPolicy: fakePersonalPolicy,
8216+
isFromGlobalCreate: true,
8217+
newIouRequestType: CONST.IOU.REQUEST_TYPE.MANUAL,
8218+
report: fakeReport,
8219+
parentReport: fakeParentReport,
8220+
currentDate,
8221+
currentUserPersonalDetails,
8222+
hasOnlyPersonalPolicies: false,
8223+
draftTransactions,
8224+
});
8225+
})
8226+
.then(async () => {
8227+
// The other draft transaction should be removed (Onyx returns undefined for removed keys)
8228+
expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${otherDraftTransactionID}`)).toBeUndefined();
8229+
// The optimistic transaction should be updated with the new transaction result (not removed)
8230+
expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${CONST.IOU.OPTIMISTIC_TRANSACTION_ID}`)).toStrictEqual(transactionResult);
8231+
});
8232+
});
8233+
8234+
it('should remove multiple draft transactions when draftTransactions contains several entries', async () => {
8235+
const draftTransactionID1 = '111111';
8236+
const draftTransactionID2 = '222222';
8237+
const draftTransaction1: Transaction = {
8238+
...createRandomTransaction(4),
8239+
transactionID: draftTransactionID1,
8240+
};
8241+
const draftTransaction2: Transaction = {
8242+
...createRandomTransaction(5),
8243+
transactionID: draftTransactionID2,
8244+
};
8245+
8246+
// Set up multiple draft transactions
8247+
await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${draftTransactionID1}`, draftTransaction1);
8248+
await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${draftTransactionID2}`, draftTransaction2);
8249+
8250+
const draftTransactions = {
8251+
[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${draftTransactionID1}`]: draftTransaction1,
8252+
[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${draftTransactionID2}`]: draftTransaction2,
8253+
};
8254+
8255+
await waitForBatchedUpdates()
8256+
.then(() => {
8257+
initMoneyRequest({
8258+
reportID: fakeReport.reportID,
8259+
policy: fakePolicy,
8260+
personalPolicy: fakePersonalPolicy,
8261+
isFromGlobalCreate: true,
8262+
newIouRequestType: CONST.IOU.REQUEST_TYPE.MANUAL,
8263+
report: fakeReport,
8264+
parentReport: fakeParentReport,
8265+
currentDate,
8266+
currentUserPersonalDetails,
8267+
hasOnlyPersonalPolicies: false,
8268+
draftTransactions,
8269+
});
8270+
})
8271+
.then(async () => {
8272+
// Both draft transactions should be removed (Onyx returns undefined for removed keys)
8273+
expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${draftTransactionID1}`)).toBeUndefined();
8274+
expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${draftTransactionID2}`)).toBeUndefined();
8275+
// The optimistic transaction should be created
8276+
expect(await getOnyxValue(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${CONST.IOU.OPTIMISTIC_TRANSACTION_ID}`)).toStrictEqual(transactionResult);
8277+
});
8278+
});
81488279
});
81498280

81508281
describe('updateMoneyRequestAmountAndCurrency', () => {

0 commit comments

Comments
 (0)