, policies: OnyxCollection, policies: OnyxCollection, betas: OnyxEntry): boolean {
- if (isThread(report) && ReportActionsUtils.isPendingRemove(ReportActionsUtils.getParentReportAction(report))) {
- return false;
- }
-
// We hide default rooms (it's basically just domain rooms now) from people who aren't on the defaultRooms beta.
if (isDefaultRoom(report) && !canSeeDefaultRoom(report, policies, betas)) {
return false;
@@ -3627,6 +3621,7 @@ function canAccessReport(report: OnyxEntry, policies: OnyxCollection, reportID: st
reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.CHRONOSOOOLIST;
if (ReportActionsUtils.isWhisperAction(reportAction)) {
// Allow flagging welcome message whispers as they can be set by any room creator
- if (report?.welcomeMessage && !isCurrentUserAction && isOriginalMessageHaveHtml && reportAction?.originalMessage?.html === report.welcomeMessage) {
+ if (report?.description && !isCurrentUserAction && isOriginalMessageHaveHtml && reportAction?.originalMessage?.html === report.description) {
return true;
}
@@ -4190,7 +4185,7 @@ function isValidReportIDFromPath(reportIDFromPath: string): boolean {
/**
* Return the errors we have when creating a chat or a workspace room
*/
-function getAddWorkspaceRoomOrChatReportErrors(report: OnyxEntry): Record | null | undefined {
+function getAddWorkspaceRoomOrChatReportErrors(report: OnyxEntry): Errors | null | undefined {
// We are either adding a workspace room, or we're creating a chat, it isn't possible for both of these to have errors for the same report at the same time, so
// simply looking up the first truthy value will get the relevant property if it's set.
return report?.errorFields?.addWorkspaceRoom ?? report?.errorFields?.createChat;
@@ -4575,10 +4570,17 @@ function getRoom(type: ValueOf, policyID: string)
}
/**
- * We only want policy owners and admins to be able to modify the welcome message, but not in thread chat.
+ * We only want policy members who are members of the report to be able to modify the report description, but not in thread chat.
*/
-function shouldDisableWelcomeMessage(report: OnyxEntry, policy: OnyxEntry): boolean {
- return isMoneyRequestReport(report) || isArchivedRoom(report) || !isChatRoom(report) || isChatThread(report) || !PolicyUtils.isPolicyAdmin(policy);
+function canEditReportDescription(report: OnyxEntry, policy: OnyxEntry | undefined): boolean {
+ return (
+ !isMoneyRequestReport(report) &&
+ !isArchivedRoom(report) &&
+ isChatRoom(report) &&
+ !isChatThread(report) &&
+ !isEmpty(policy) &&
+ (getVisibleMemberIDs(report).includes(currentUserAccountID ?? 0) || getParticipantsIDs(report).includes(currentUserAccountID ?? 0))
+ );
}
/**
* Checks if report action has error when smart scanning
@@ -4638,6 +4640,21 @@ function shouldDisplayThreadReplies(reportAction: OnyxEntry, repor
return hasReplies && !!reportAction?.childCommenterCount && !isThreadFirstChat(reportAction, reportID);
}
+/**
+ * Check if money report has any transactions updated optimistically
+ */
+function hasUpdatedTotal(report: OnyxEntry): boolean {
+ if (!report) {
+ return true;
+ }
+
+ const transactions = TransactionUtils.getAllReportTransactions(report.reportID);
+ const hasPendingTransaction = transactions.some((transaction) => !!transaction.pendingAction);
+ const hasTransactionWithDifferentCurrency = transactions.some((transaction) => transaction.currency !== report.currency);
+
+ return !(hasPendingTransaction && hasTransactionWithDifferentCurrency);
+}
+
/**
* Disable reply in thread action if:
*
@@ -4663,6 +4680,78 @@ function shouldDisableThread(reportAction: OnyxEntry, reportID: st
);
}
+function getAllAncestorReportActions(report: Report | null | undefined, shouldHideThreadDividerLine: boolean): Ancestor[] {
+ if (!report) {
+ return [];
+ }
+ const allAncestors: Ancestor[] = [];
+ let parentReportID = report.parentReportID;
+ let parentReportActionID = report.parentReportActionID;
+
+ // Store the child of parent report
+ let currentReport = report;
+ let currentUnread = shouldHideThreadDividerLine;
+
+ while (parentReportID) {
+ const parentReport = getReport(parentReportID);
+ const parentReportAction = ReportActionsUtils.getReportAction(parentReportID, parentReportActionID ?? '0');
+
+ if (!parentReportAction || ReportActionsUtils.isTransactionThread(parentReportAction) || !parentReport) {
+ break;
+ }
+
+ const isParentReportActionUnread = ReportActionsUtils.isCurrentActionUnread(parentReport, parentReportAction);
+ allAncestors.push({
+ report: currentReport,
+ reportAction: parentReportAction,
+ shouldDisplayNewMarker: isParentReportActionUnread,
+ // We should hide the thread divider line if the previous ancestor action is unread
+ shouldHideThreadDividerLine: currentUnread,
+ });
+ parentReportID = parentReport?.parentReportID;
+ parentReportActionID = parentReport?.parentReportActionID;
+ if (!isEmptyObject(parentReport)) {
+ currentReport = parentReport;
+ currentUnread = isParentReportActionUnread;
+ }
+ }
+
+ return allAncestors.reverse();
+}
+
+function getAllAncestorReportActionIDs(report: Report | null | undefined): AncestorIDs {
+ if (!report) {
+ return {
+ reportIDs: [],
+ reportActionsIDs: [],
+ };
+ }
+
+ const allAncestorIDs: AncestorIDs = {
+ reportIDs: [],
+ reportActionsIDs: [],
+ };
+ let parentReportID = report.parentReportID;
+ let parentReportActionID = report.parentReportActionID;
+
+ while (parentReportID) {
+ const parentReport = getReport(parentReportID);
+ const parentReportAction = ReportActionsUtils.getReportAction(parentReportID, parentReportActionID ?? '0');
+
+ if (!parentReportAction || ReportActionsUtils.isTransactionThread(parentReportAction) || !parentReport) {
+ break;
+ }
+
+ allAncestorIDs.reportIDs.push(parentReportID ?? '');
+ allAncestorIDs.reportActionsIDs.push(parentReportActionID ?? '');
+
+ parentReportID = parentReport?.parentReportID;
+ parentReportActionID = parentReport?.parentReportActionID;
+ }
+
+ return allAncestorIDs;
+}
+
function canBeAutoReimbursed(report: OnyxEntry, policy: OnyxEntry = null): boolean {
if (!policy) {
return false;
@@ -4849,9 +4938,9 @@ export {
getReimbursementDeQueuedActionMessage,
getPersonalDetailsForAccountID,
getRoom,
+ canEditReportDescription,
doesTransactionThreadHaveViolations,
hasViolations,
- shouldDisableWelcomeMessage,
navigateToPrivateNotes,
canEditWriteCapability,
hasSmartscanError,
@@ -4860,11 +4949,16 @@ export {
shouldDisableThread,
doesReportBelongToWorkspace,
getChildReportNotificationPreference,
+ getAllAncestorReportActions,
isReportParticipant,
isValidReport,
+ getReportDescriptionText,
isReportFieldOfTypeTitle,
+ isIOUReportUsingReport,
+ hasUpdatedTotal,
isReportFieldDisabled,
getAvailableReportFields,
+ getAllAncestorReportActionIDs,
};
export type {
@@ -4876,4 +4970,7 @@ export type {
OptimisticAddCommentReportAction,
OptimisticCreatedReportAction,
OptimisticClosedReportAction,
+ Ancestor,
+ OptimisticIOUReportAction,
+ TransactionDetails,
};
diff --git a/src/libs/SelectionScraper/index.ts b/src/libs/SelectionScraper/index.ts
index 955fe693c856..8d7f3e7055fc 100644
--- a/src/libs/SelectionScraper/index.ts
+++ b/src/libs/SelectionScraper/index.ts
@@ -112,6 +112,9 @@ const replaceNodes = (dom: Node, isChildOfEditorElement: boolean): Node => {
// Encoding HTML chars '< >' in the text, because any HTML will be removed in stripHTML method.
if (dom.type.toString() === 'text' && dom instanceof DataNode) {
data = Str.htmlEncode(dom.data);
+ if (dom.parent instanceof Element && dom.parent?.attribs?.id === 'email-with-break-opportunities') {
+ data = data.replaceAll('\u200b', '');
+ }
} else if (dom instanceof Element) {
domName = dom.name;
if (dom.attribs?.[tagAttribute]) {
diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts
index 02c32e089016..2347f5b9f5c5 100644
--- a/src/libs/SidebarUtils.ts
+++ b/src/libs/SidebarUtils.ts
@@ -253,7 +253,7 @@ function getOptionData({
const result: ReportUtils.OptionData = {
text: '',
alternateText: null,
- allReportErrors: undefined,
+ allReportErrors: OptionsListUtils.getAllReportErrors(report, reportActions),
brickRoadIndicator: null,
tooltipText: null,
subtitle: null,
@@ -295,7 +295,6 @@ function getOptionData({
result.isMoneyRequestReport = ReportUtils.isMoneyRequestReport(report);
result.shouldShowSubscript = ReportUtils.shouldReportShowSubscript(report);
result.pendingAction = report.pendingFields ? report.pendingFields.addWorkspaceRoom || report.pendingFields.createChat : undefined;
- result.allReportErrors = OptionsListUtils.getAllReportErrors(report, reportActions);
result.brickRoadIndicator = hasErrors || hasViolations ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : '';
result.ownerAccountID = report.ownerAccountID;
result.managerID = report.managerID;
diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts
index 68085c8d1255..8a814f311481 100644
--- a/src/libs/TransactionUtils.ts
+++ b/src/libs/TransactionUtils.ts
@@ -6,16 +6,12 @@ import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {RecentWaypoint, Report, ReportAction, Transaction, TransactionViolation} from '@src/types/onyx';
import type {PolicyTaxRate, PolicyTaxRates} from '@src/types/onyx/PolicyTaxRates';
-import type {Comment, Receipt, Waypoint, WaypointCollection} from '@src/types/onyx/Transaction';
+import type {Comment, Receipt, TransactionChanges, Waypoint, WaypointCollection} from '@src/types/onyx/Transaction';
import type {EmptyObject} from '@src/types/utils/EmptyObject';
import {isCorporateCard, isExpensifyCard} from './CardUtils';
import DateUtils from './DateUtils';
import * as NumberUtils from './NumberUtils';
-type AdditionalTransactionChanges = {comment?: string; waypoints?: WaypointCollection};
-
-type TransactionChanges = Partial & AdditionalTransactionChanges;
-
let allTransactions: OnyxCollection = {};
Onyx.connect({
@@ -266,7 +262,7 @@ function getDescription(transaction: OnyxEntry): string {
/**
* Return the amount field from the transaction, return the modifiedAmount if present.
*/
-function getAmount(transaction: OnyxEntry, isFromExpenseReport: boolean): number {
+function getAmount(transaction: OnyxEntry, isFromExpenseReport?: boolean): number {
// IOU requests cannot have negative values but they can be stored as negative values, let's return absolute value
if (!isFromExpenseReport) {
const amount = transaction?.modifiedAmount ?? 0;
@@ -393,8 +389,8 @@ function getHeaderTitleTranslationKey(transaction: Transaction): string {
/**
* Determine whether a transaction is made with an Expensify card.
*/
-function isExpensifyCardTransaction(transaction: Transaction): boolean {
- if (!transaction.cardID) {
+function isExpensifyCardTransaction(transaction: OnyxEntry): boolean {
+ if (!transaction?.cardID) {
return false;
}
return isExpensifyCard(transaction.cardID);
@@ -403,7 +399,7 @@ function isExpensifyCardTransaction(transaction: Transaction): boolean {
/**
* Determine whether a transaction is made with a card (Expensify or Company Card).
*/
-function isCardTransaction(transaction: Transaction): boolean {
+function isCardTransaction(transaction: OnyxEntry): boolean {
const cardID = transaction?.cardID ?? 0;
return isCorporateCard(cardID);
}
@@ -411,8 +407,8 @@ function isCardTransaction(transaction: Transaction): boolean {
/**
* Check if the transaction status is set to Pending.
*/
-function isPending(transaction: Transaction): boolean {
- if (!transaction.status) {
+function isPending(transaction: OnyxEntry): boolean {
+ if (!transaction?.status) {
return false;
}
return transaction.status === CONST.TRANSACTION.STATUS.PENDING;
diff --git a/src/libs/UserUtils.ts b/src/libs/UserUtils.ts
index 6ec386679a32..a8c918bc5def 100644
--- a/src/libs/UserUtils.ts
+++ b/src/libs/UserUtils.ts
@@ -176,8 +176,8 @@ function getAvatar(avatarSource?: AvatarSource, accountID?: number): AvatarSourc
* @param avatarURL - the avatar source from user's personalDetails
* @param accountID - the accountID of the user
*/
-function getAvatarUrl(avatarURL: string, accountID: number): string {
- return isDefaultAvatar(avatarURL) ? getDefaultAvatarURL(accountID) : avatarURL;
+function getAvatarUrl(avatarSource: AvatarSource | undefined, accountID: number): AvatarSource {
+ return isDefaultAvatar(avatarSource) ? getDefaultAvatarURL(accountID) : avatarSource;
}
/**
diff --git a/src/libs/ValidationUtils.ts b/src/libs/ValidationUtils.ts
index 9b2b1d01b80b..7ee7d6c4f048 100644
--- a/src/libs/ValidationUtils.ts
+++ b/src/libs/ValidationUtils.ts
@@ -4,6 +4,7 @@ import {URL_REGEX_WITH_REQUIRED_PROTOCOL} from 'expensify-common/lib/Url';
import isDate from 'lodash/isDate';
import isEmpty from 'lodash/isEmpty';
import isObject from 'lodash/isObject';
+import type {OnyxCollection} from 'react-native-onyx';
import CONST from '@src/CONST';
import type {Report} from '@src/types/onyx';
import type * as OnyxCommon from '@src/types/onyx/OnyxCommon';
@@ -74,7 +75,7 @@ function isValidPastDate(date: string | Date): boolean {
/**
* Used to validate a value that is "required".
*/
-function isRequiredFulfilled(value: string | Date | unknown[] | Record): boolean {
+function isRequiredFulfilled(value: string | Date | unknown[] | Record | null): boolean {
if (typeof value === 'string') {
return !StringUtils.isEmptyString(value);
}
@@ -361,8 +362,8 @@ function isReservedRoomName(roomName: string): boolean {
/**
* Checks if the room name already exists.
*/
-function isExistingRoomName(roomName: string, reports: Record, policyID: string): boolean {
- return Object.values(reports).some((report) => report && report.policyID === policyID && report.reportName === roomName);
+function isExistingRoomName(roomName: string, reports: OnyxCollection, policyID: string): boolean {
+ return Object.values(reports ?? {}).some((report) => report && report.policyID === policyID && report.reportName === roomName);
}
/**
diff --git a/src/libs/Violations/ViolationsUtils.ts b/src/libs/Violations/ViolationsUtils.ts
index c0558d7487cf..9a05ba4d87ed 100644
--- a/src/libs/Violations/ViolationsUtils.ts
+++ b/src/libs/Violations/ViolationsUtils.ts
@@ -1,5 +1,6 @@
import reject from 'lodash/reject';
import Onyx from 'react-native-onyx';
+import type {OnyxUpdate} from 'react-native-onyx';
import type {Phrase, PhraseParameters} from '@libs/Localize';
import type {TranslationPaths} from '@src/languages/types';
import ONYXKEYS from '@src/ONYXKEYS';
@@ -17,17 +18,13 @@ const ViolationsUtils = {
policyTags: PolicyTags,
policyRequiresCategories: boolean,
policyCategories: PolicyCategories,
- ): {
- onyxMethod: string;
- key: string;
- value: TransactionViolation[];
- } {
+ ): OnyxUpdate {
let newTransactionViolations = [...transactionViolations];
if (policyRequiresCategories) {
const hasCategoryOutOfPolicyViolation = transactionViolations.some((violation) => violation.name === 'categoryOutOfPolicy');
const hasMissingCategoryViolation = transactionViolations.some((violation) => violation.name === 'missingCategory');
- const isCategoryInPolicy = Boolean(policyCategories[transaction.category]?.enabled);
+ const isCategoryInPolicy = !!policyCategories[transaction.category ?? '']?.enabled;
// Add 'categoryOutOfPolicy' violation if category is not in policy
if (!hasCategoryOutOfPolicyViolation && transaction.category && !isCategoryInPolicy) {
@@ -53,7 +50,7 @@ const ViolationsUtils = {
if (policyRequiresTags) {
const hasTagOutOfPolicyViolation = transactionViolations.some((violation) => violation.name === 'tagOutOfPolicy');
const hasMissingTagViolation = transactionViolations.some((violation) => violation.name === 'missingTag');
- const isTagInPolicy = Boolean(policyTags[transaction.tag]?.enabled);
+ const isTagInPolicy = !!policyTags[transaction.tag ?? '']?.enabled;
// Add 'tagOutOfPolicy' violation if tag is not in policy
if (!hasTagOutOfPolicyViolation && transaction.tag && !isTagInPolicy) {
@@ -155,7 +152,7 @@ const ViolationsUtils = {
brokenBankConnection: violation.data?.brokenBankConnection ?? false,
isAdmin: violation.data?.isAdmin ?? false,
email: violation.data?.email,
- isTransactionOlderThan7Days: Boolean(violation.data?.isTransactionOlderThan7Days),
+ isTransactionOlderThan7Days: !!violation.data?.isTransactionOlderThan7Days,
member: violation.data?.member,
});
case 'smartscanFailed':
diff --git a/src/libs/actions/EmojiPickerAction.ts b/src/libs/actions/EmojiPickerAction.ts
index 56a5f34c0b8e..0fc21713c608 100644
--- a/src/libs/actions/EmojiPickerAction.ts
+++ b/src/libs/actions/EmojiPickerAction.ts
@@ -26,6 +26,7 @@ type EmojiPickerRef = {
anchorOrigin?: AnchorOrigin,
onWillShow?: OnWillShowPicker,
id?: string,
+ activeEmoji?: string,
) => void;
isActive: (id: string) => boolean;
clearActive: () => void;
@@ -55,12 +56,13 @@ function showEmojiPicker(
anchorOrigin?: AnchorOrigin,
onWillShow: OnWillShowPicker = () => {},
id?: string,
+ activeEmoji?: string,
) {
if (!emojiPickerRef.current) {
return;
}
- emojiPickerRef.current.showEmojiPicker(onModalHide, onEmojiSelected, emojiPopoverAnchor, anchorOrigin, onWillShow, id);
+ emojiPickerRef.current.showEmojiPicker(onModalHide, onEmojiSelected, emojiPopoverAnchor, anchorOrigin, onWillShow, id, activeEmoji);
}
/**
diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.ts
similarity index 62%
rename from src/libs/actions/IOU.js
rename to src/libs/actions/IOU.ts
index f2bdb097497e..a7a82e642e62 100644
--- a/src/libs/actions/IOU.js
+++ b/src/libs/actions/IOU.ts
@@ -1,12 +1,29 @@
+import type {StackScreenProps} from '@react-navigation/stack';
import {format} from 'date-fns';
import fastMerge from 'expensify-common/lib/fastMerge';
import Str from 'expensify-common/lib/str';
-import lodashGet from 'lodash/get';
-import lodashHas from 'lodash/has';
import Onyx from 'react-native-onyx';
-import _ from 'underscore';
+import type {OnyxCollection, OnyxEntry, OnyxUpdate} from 'react-native-onyx';
+import type {ValueOf} from 'type-fest';
import ReceiptGeneric from '@assets/images/receipt-generic.png';
import * as API from '@libs/API';
+import type {
+ ApproveMoneyRequestParams,
+ CompleteSplitBillParams,
+ CreateDistanceRequestParams,
+ DeleteMoneyRequestParams,
+ DetachReceiptParams,
+ EditMoneyRequestParams,
+ PayMoneyRequestParams,
+ ReplaceReceiptParams,
+ RequestMoneyParams,
+ SendMoneyParams,
+ SplitBillParams,
+ StartSplitBillParams,
+ SubmitReportParams,
+ UpdateMoneyRequestParams,
+} from '@libs/API/parameters';
+import {WRITE_COMMANDS} from '@libs/API/types';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import DateUtils from '@libs/DateUtils';
import * as ErrorUtils from '@libs/ErrorUtils';
@@ -21,128 +38,198 @@ import Permissions from '@libs/Permissions';
import * as PolicyUtils from '@libs/PolicyUtils';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import * as ReportUtils from '@libs/ReportUtils';
+import type {OptimisticChatReport, OptimisticCreatedReportAction, OptimisticIOUReportAction, TransactionDetails} from '@libs/ReportUtils';
import * as TransactionUtils from '@libs/TransactionUtils';
import * as UserUtils from '@libs/UserUtils';
import ViolationsUtils from '@libs/Violations/ViolationsUtils';
+import type {MoneyRequestNavigatorParamList} from '@navigation/types';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
+import type SCREENS from '@src/SCREENS';
+import type * as OnyxTypes from '@src/types/onyx';
+import type {Participant, Split} from '@src/types/onyx/IOU';
+import type {ErrorFields, Errors} from '@src/types/onyx/OnyxCommon';
+import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage';
+import type ReportAction from '@src/types/onyx/ReportAction';
+import type {OnyxData} from '@src/types/onyx/Request';
+import type {Comment, Receipt, ReceiptSource, TaxRate, TransactionChanges, WaypointCollection} from '@src/types/onyx/Transaction';
+import type {EmptyObject} from '@src/types/utils/EmptyObject';
+import {isEmptyObject} from '@src/types/utils/EmptyObject';
import * as Policy from './Policy';
import * as Report from './Report';
-let betas;
+type MoneyRequestRoute = StackScreenProps['route'];
+
+type IOURequestType = ValueOf;
+
+type OneOnOneIOUReport = OnyxTypes.Report | undefined | null;
+
+type MoneyRequestInformation = {
+ payerAccountID: number;
+ payerEmail: string;
+ iouReport: OnyxTypes.Report;
+ chatReport: OnyxTypes.Report;
+ transaction: OnyxTypes.Transaction;
+ iouAction: OptimisticIOUReportAction;
+ createdChatReportActionID: string;
+ createdIOUReportActionID: string;
+ reportPreviewAction: OnyxTypes.ReportAction;
+ onyxData: OnyxData;
+};
+
+type SplitData = {
+ chatReportID: string;
+ transactionID: string;
+ reportActionID: string;
+ policyID?: string;
+ createdReportActionID?: string;
+};
+
+type SplitsAndOnyxData = {
+ splitData: SplitData;
+ splits: Split[];
+ onyxData: OnyxData;
+};
+
+type UpdateMoneyRequestData = {
+ params: UpdateMoneyRequestParams;
+ onyxData: OnyxData;
+};
+
+type PayMoneyRequestData = {
+ params: PayMoneyRequestParams;
+ optimisticData: OnyxUpdate[];
+ successData: OnyxUpdate[];
+ failureData: OnyxUpdate[];
+};
+
+type SendMoneyParamsData = {
+ params: SendMoneyParams;
+ optimisticData: OnyxUpdate[];
+ successData: OnyxUpdate[];
+ failureData: OnyxUpdate[];
+};
+
+type OutstandingChildRequest = {
+ hasOutstandingChildRequest?: boolean;
+};
+
+let betas: OnyxTypes.Beta[] = [];
Onyx.connect({
key: ONYXKEYS.BETAS,
- callback: (val) => (betas = val || []),
+ callback: (value) => (betas = value ?? []),
});
-let allPersonalDetails;
+let allPersonalDetails: OnyxTypes.PersonalDetailsList = {};
Onyx.connect({
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
- callback: (val) => {
- allPersonalDetails = val || {};
+ callback: (value) => {
+ allPersonalDetails = value ?? {};
},
});
-let allReports;
+let allReports: OnyxCollection = null;
Onyx.connect({
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
- callback: (val) => (allReports = val),
+ callback: (value) => (allReports = value),
});
-let allTransactions;
+let allTransactions: NonNullable> = {};
Onyx.connect({
key: ONYXKEYS.COLLECTION.TRANSACTION,
waitForCollectionCallback: true,
- callback: (val) => {
- if (!val) {
+ callback: (value) => {
+ if (!value) {
allTransactions = {};
return;
}
- allTransactions = val;
+ allTransactions = value;
},
});
-let allTransactionDrafts = {};
+let allTransactionDrafts: NonNullable> = {};
Onyx.connect({
key: ONYXKEYS.COLLECTION.TRANSACTION_DRAFT,
waitForCollectionCallback: true,
- callback: (val) => {
- allTransactionDrafts = val || {};
+ callback: (value) => {
+ allTransactionDrafts = value ?? {};
},
});
-let allTransactionViolations;
+let allTransactionViolations: NonNullable> = {};
Onyx.connect({
key: ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS,
waitForCollectionCallback: true,
- callback: (val) => {
- if (!val) {
+ callback: (value) => {
+ if (!value) {
allTransactionViolations = {};
return;
}
- allTransactionViolations = val;
+ allTransactionViolations = value;
},
});
-let allDraftSplitTransactions;
+let allDraftSplitTransactions: NonNullable> = {};
Onyx.connect({
key: ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT,
waitForCollectionCallback: true,
- callback: (val) => {
- allDraftSplitTransactions = val || {};
+ callback: (value) => {
+ allDraftSplitTransactions = value ?? {};
},
});
-let allNextSteps = {};
+let allNextSteps: NonNullable> = {};
Onyx.connect({
key: ONYXKEYS.COLLECTION.NEXT_STEP,
waitForCollectionCallback: true,
- callback: (val) => {
- allNextSteps = val || {};
+ callback: (value) => {
+ allNextSteps = value ?? {};
},
});
-let userAccountID = '';
+let userAccountID = -1;
let currentUserEmail = '';
Onyx.connect({
key: ONYXKEYS.SESSION,
- callback: (val) => {
- currentUserEmail = lodashGet(val, 'email', '');
- userAccountID = lodashGet(val, 'accountID', '');
+ callback: (value) => {
+ currentUserEmail = value?.email ?? '';
+ userAccountID = value?.accountID ?? -1;
},
});
-let currentUserPersonalDetails = {};
+let currentUserPersonalDetails: OnyxTypes.PersonalDetails | EmptyObject = {};
Onyx.connect({
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
- callback: (val) => {
- currentUserPersonalDetails = lodashGet(val, userAccountID, {});
+ callback: (value) => {
+ currentUserPersonalDetails = value?.[userAccountID] ?? {};
},
});
-let currentDate = '';
+let currentDate: OnyxEntry = '';
Onyx.connect({
key: ONYXKEYS.CURRENT_DATE,
- callback: (val) => {
- currentDate = val;
+ callback: (value) => {
+ currentDate = value;
},
});
/**
* Initialize money request info
- * @param {String} reportID to attach the transaction to
- * @param {Boolean} isFromGlobalCreate
- * @param {String} [iouRequestType] one of manual/scan/distance
+ * @param reportID to attach the transaction to
+ * @param iouRequestType one of manual/scan/distance
*/
-function startMoneyRequest_temporaryForRefactor(reportID, isFromGlobalCreate, iouRequestType = CONST.IOU.REQUEST_TYPE.MANUAL) {
+// eslint-disable-next-line @typescript-eslint/naming-convention
+function startMoneyRequest_temporaryForRefactor(reportID: string, isFromGlobalCreate: boolean, iouRequestType: IOURequestType = CONST.IOU.REQUEST_TYPE.MANUAL) {
// Generate a brand new transactionID
const newTransactionID = CONST.IOU.OPTIMISTIC_TRANSACTION_ID;
+ // Disabling this line since currentDate can be an empty string
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
const created = currentDate || format(new Date(), 'yyyy-MM-dd');
- const comment = {};
+ const comment: Comment = {};
// Add initial empty waypoints when starting a distance request
if (iouRequestType === CONST.IOU.REQUEST_TYPE.DISTANCE) {
@@ -158,7 +245,7 @@ function startMoneyRequest_temporaryForRefactor(reportID, isFromGlobalCreate, io
amount: 0,
comment,
created,
- currency: lodashGet(currentUserPersonalDetails, 'localCurrencyCode', CONST.CURRENCY.USD),
+ currency: currentUserPersonalDetails.localCurrencyCode ?? CONST.CURRENCY.USD,
iouRequestType,
reportID,
transactionID: newTransactionID,
@@ -167,123 +254,88 @@ function startMoneyRequest_temporaryForRefactor(reportID, isFromGlobalCreate, io
});
}
-/**
- * @param {String} transactionID
- */
-function clearMoneyRequest(transactionID) {
+function clearMoneyRequest(transactionID: string) {
Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, null);
}
-/**
- * @param {String} transactionID
- * @param {Number} amount
- * @param {String} currency
- */
-function setMoneyRequestAmount_temporaryForRefactor(transactionID, amount, currency) {
+// eslint-disable-next-line @typescript-eslint/naming-convention
+function setMoneyRequestAmount_temporaryForRefactor(transactionID: string, amount: number, currency: string, removeOriginalCurrency = false) {
+ if (removeOriginalCurrency) {
+ Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {amount, currency, originalCurrency: null});
+ return;
+ }
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {amount, currency});
}
-/**
- * @param {String} transactionID
- * @param {String} created
- */
-function setMoneyRequestCreated_temporaryForRefactor(transactionID, created) {
+// eslint-disable-next-line @typescript-eslint/naming-convention
+function setMoneyRequestCreated_temporaryForRefactor(transactionID: string, created: string) {
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {created});
}
-/**
- * @param {String} transactionID
- * @param {String} currency
- */
-function setMoneyRequestCurrency_temporaryForRefactor(transactionID, currency) {
+// eslint-disable-next-line @typescript-eslint/naming-convention
+function setMoneyRequestCurrency_temporaryForRefactor(transactionID: string, currency: string, removeOriginalCurrency = false) {
+ if (removeOriginalCurrency) {
+ Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {currency, originalCurrency: null});
+ return;
+ }
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {currency});
}
-/**
- * @param {String} transactionID
- * @param {String} comment
- */
-function setMoneyRequestDescription_temporaryForRefactor(transactionID, comment) {
+// eslint-disable-next-line @typescript-eslint/naming-convention
+function setMoneyRequestOriginalCurrency_temporaryForRefactor(transactionID: string, originalCurrency: string) {
+ Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {originalCurrency});
+}
+
+// eslint-disable-next-line @typescript-eslint/naming-convention
+function setMoneyRequestDescription_temporaryForRefactor(transactionID: string, comment: string) {
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {comment: {comment: comment.trim()}});
}
-/**
- * @param {String} transactionID
- * @param {String} merchant
- */
-function setMoneyRequestMerchant_temporaryForRefactor(transactionID, merchant) {
+// eslint-disable-next-line @typescript-eslint/naming-convention
+function setMoneyRequestMerchant_temporaryForRefactor(transactionID: string, merchant: string) {
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {merchant: merchant.trim()});
}
-/**
- * @param {String} transactionID
- * @param {String} category
- */
-function setMoneyRequestCategory_temporaryForRefactor(transactionID, category) {
+// eslint-disable-next-line @typescript-eslint/naming-convention
+function setMoneyRequestCategory_temporaryForRefactor(transactionID: string, category: string) {
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {category});
}
-/*
- * @param {String} transactionID
- */
-function resetMoneyRequestCategory_temporaryForRefactor(transactionID) {
+// eslint-disable-next-line @typescript-eslint/naming-convention
+function resetMoneyRequestCategory_temporaryForRefactor(transactionID: string) {
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {category: null});
}
-/*
- * @param {String} transactionID
- * @param {String} tag
- */
-function setMoneyRequestTag_temporaryForRefactor(transactionID, tag) {
+function setMoneyRequestTag(transactionID: string, tag: string) {
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {tag});
}
-/*
- * @param {String} transactionID
- */
-function resetMoneyRequestTag_temporaryForRefactor(transactionID) {
- Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {tag: null});
-}
-
-/**
- * @param {String} transactionID
- * @param {Boolean} billable
- */
-function setMoneyRequestBillable_temporaryForRefactor(transactionID, billable) {
+// eslint-disable-next-line @typescript-eslint/naming-convention
+function setMoneyRequestBillable_temporaryForRefactor(transactionID: string, billable: boolean) {
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {billable});
}
-/**
- * @param {String} transactionID
- * @param {Object[]} participants
- */
-function setMoneyRequestParticipants_temporaryForRefactor(transactionID, participants) {
+// eslint-disable-next-line @typescript-eslint/naming-convention
+function setMoneyRequestParticipants_temporaryForRefactor(transactionID: string, participants: Participant[]) {
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {participants});
}
-/**
- * @param {String} transactionID
- * @param {String} source
- * @param {String} filename
- * @param {Boolean} isDraft
- */
-function setMoneyRequestReceipt(transactionID, source, filename, isDraft) {
+function setMoneyRequestReceipt(transactionID: string, source: string, filename: string, isDraft: boolean) {
Onyx.merge(`${isDraft ? ONYXKEYS.COLLECTION.TRANSACTION_DRAFT : ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {
receipt: {source},
filename,
});
}
-/**
- * Reset money request info from the store with its initial value
- * @param {String} id
- */
+/** Reset money request info from the store with its initial value */
function resetMoneyRequestInfo(id = '') {
+ // Disabling this line since currentDate can be an empty string
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
const created = currentDate || format(new Date(), CONST.DATE.FNS_FORMAT_STRING);
Onyx.merge(ONYXKEYS.IOU, {
id,
amount: 0,
- currency: lodashGet(currentUserPersonalDetails, 'localCurrencyCode', CONST.CURRENCY.USD),
+ currency: currentUserPersonalDetails.localCurrencyCode ?? CONST.CURRENCY.USD,
comment: '',
participants: [],
merchant: CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT,
@@ -298,27 +350,15 @@ function resetMoneyRequestInfo(id = '') {
});
}
-/**
- * Helper function to get the receipt error for money requests, or the generic error if there's no receipt
- *
- * @param {Object} receipt
- * @param {String} filename
- * @param {Boolean} [isScanRequest]
- * @returns {Object}
- */
-function getReceiptError(receipt, filename, isScanRequest = true) {
- return _.isEmpty(receipt) || !isScanRequest
+/** Helper function to get the receipt error for money requests, or the generic error if there's no receipt */
+function getReceiptError(receipt?: Receipt, filename?: string, isScanRequest = true): Errors | ErrorFields {
+ return isEmptyObject(receipt) || !isScanRequest
? ErrorUtils.getMicroSecondOnyxError('iou.error.genericCreateFailureMessage')
- : ErrorUtils.getMicroSecondOnyxErrorObject({error: CONST.IOU.RECEIPT_ERROR, source: receipt.source, filename});
+ : ErrorUtils.getMicroSecondOnyxErrorObject({error: CONST.IOU.RECEIPT_ERROR, source: receipt.source?.toString() ?? '', filename: filename ?? ''});
}
-/**
- * Return the object to update hasOutstandingChildRequest
- * @param {Object} [policy]
- * @param {Boolean} needsToBeManuallySubmitted
- * @returns {Object}
- */
-function getOutstandingChildRequest(policy, needsToBeManuallySubmitted) {
+/** Return the object to update hasOutstandingChildRequest */
+function getOutstandingChildRequest(needsToBeManuallySubmitted: boolean, policy: OnyxEntry | EmptyObject = null): OutstandingChildRequest {
if (!needsToBeManuallySubmitted) {
return {
hasOutstandingChildRequest: false,
@@ -335,49 +375,31 @@ function getOutstandingChildRequest(policy, needsToBeManuallySubmitted) {
return {};
}
-/**
- * Builds the Onyx data for a money request.
- *
- * @param {Object} chatReport
- * @param {Object} iouReport
- * @param {Object} transaction
- * @param {Object} chatCreatedAction
- * @param {Object} iouCreatedAction
- * @param {Object} iouAction
- * @param {Object} optimisticPersonalDetailListAction
- * @param {Object} reportPreviewAction
- * @param {Array} optimisticPolicyRecentlyUsedCategories
- * @param {Array} optimisticPolicyRecentlyUsedTags
- * @param {boolean} isNewChatReport
- * @param {boolean} shouldCreateNewMoneyRequestReport
- * @param {Object} policy - May be undefined, an empty object, or an object matching the Policy type (src/types/onyx/Policy.ts)
- * @param {Array} policyTags
- * @param {Array} policyCategories
- * @param {Boolean} needsToBeManuallySubmitted
- * @returns {Array} - An array containing the optimistic data, success data, and failure data.
- */
+/** Builds the Onyx data for a money request */
function buildOnyxDataForMoneyRequest(
- chatReport,
- iouReport,
- transaction,
- chatCreatedAction,
- iouCreatedAction,
- iouAction,
- optimisticPersonalDetailListAction,
- reportPreviewAction,
- optimisticPolicyRecentlyUsedCategories,
- optimisticPolicyRecentlyUsedTags,
- isNewChatReport,
- shouldCreateNewMoneyRequestReport,
- policy,
- policyTags,
- policyCategories,
+ chatReport: OnyxEntry,
+ iouReport: OnyxTypes.Report,
+ transaction: OnyxTypes.Transaction,
+ chatCreatedAction: OptimisticCreatedReportAction,
+ iouCreatedAction: OptimisticCreatedReportAction,
+ iouAction: OptimisticIOUReportAction,
+ optimisticPersonalDetailListAction: OnyxTypes.PersonalDetailsList,
+ reportPreviewAction: ReportAction,
+ optimisticPolicyRecentlyUsedCategories: string[],
+ optimisticPolicyRecentlyUsedTags: OnyxTypes.RecentlyUsedTags,
+ isNewChatReport: boolean,
+ shouldCreateNewMoneyRequestReport: boolean,
+ policy?: OnyxTypes.Policy | EmptyObject,
+ policyTags?: OnyxTypes.PolicyTags,
+ policyCategories?: OnyxTypes.PolicyCategories,
needsToBeManuallySubmitted = true,
-) {
+): [OnyxUpdate[], OnyxUpdate[], OnyxUpdate[]] {
const isScanRequest = TransactionUtils.isScanRequest(transaction);
const outstandingChildRequest = getOutstandingChildRequest(needsToBeManuallySubmitted, policy);
- const optimisticData = [
- {
+ const optimisticData: OnyxUpdate[] = [];
+
+ if (chatReport) {
+ optimisticData.push({
// Use SET for new reports because it doesn't exist yet, is faster and we need the data to be available when we navigate to the chat page
onyxMethod: isNewChatReport ? Onyx.METHOD.SET : Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`,
@@ -389,14 +411,17 @@ function buildOnyxDataForMoneyRequest(
...outstandingChildRequest,
...(isNewChatReport ? {pendingFields: {createChat: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD}} : {}),
},
- },
+ });
+ }
+
+ optimisticData.push(
{
onyxMethod: shouldCreateNewMoneyRequestReport ? Onyx.METHOD.SET : Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`,
value: {
...iouReport,
- lastMessageText: iouAction.message[0].text,
- lastMessageHtml: iouAction.message[0].html,
+ lastMessageText: iouAction.message?.[0].text,
+ lastMessageHtml: iouAction.message?.[0].html,
pendingFields: {
...(shouldCreateNewMoneyRequestReport ? {createChat: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD} : {preview: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}),
},
@@ -407,22 +432,38 @@ function buildOnyxDataForMoneyRequest(
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`,
value: transaction,
},
- {
- onyxMethod: isNewChatReport ? Onyx.METHOD.SET : Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport.reportID}`,
- value: {
- ...(isNewChatReport ? {[chatCreatedAction.reportActionID]: chatCreatedAction} : {}),
- [reportPreviewAction.reportActionID]: reportPreviewAction,
- },
- },
- {
- onyxMethod: shouldCreateNewMoneyRequestReport ? Onyx.METHOD.SET : Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.reportID}`,
- value: {
- ...(shouldCreateNewMoneyRequestReport ? {[iouCreatedAction.reportActionID]: iouCreatedAction} : {}),
- [iouAction.reportActionID]: iouAction,
- },
- },
+ isNewChatReport
+ ? {
+ onyxMethod: Onyx.METHOD.SET,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport?.reportID}`,
+ value: {
+ [chatCreatedAction.reportActionID]: chatCreatedAction,
+ [reportPreviewAction.reportActionID]: reportPreviewAction,
+ },
+ }
+ : {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport?.reportID}`,
+ value: {
+ [reportPreviewAction.reportActionID]: reportPreviewAction,
+ },
+ },
+ shouldCreateNewMoneyRequestReport
+ ? {
+ onyxMethod: Onyx.METHOD.SET,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.reportID}`,
+ value: {
+ [iouCreatedAction.reportActionID]: iouCreatedAction as OnyxTypes.ReportAction,
+ [iouAction.reportActionID]: iouAction as OnyxTypes.ReportAction,
+ },
+ }
+ : {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.reportID}`,
+ value: {
+ [iouAction.reportActionID]: iouAction as OnyxTypes.ReportAction,
+ },
+ },
// Remove the temporary transaction used during the creation flow
{
@@ -430,9 +471,9 @@ function buildOnyxDataForMoneyRequest(
key: `${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${CONST.IOU.OPTIMISTIC_TRANSACTION_ID}`,
value: null,
},
- ];
+ );
- if (!_.isEmpty(optimisticPolicyRecentlyUsedCategories)) {
+ if (optimisticPolicyRecentlyUsedCategories.length) {
optimisticData.push({
onyxMethod: Onyx.METHOD.SET,
key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES}${iouReport.policyID}`,
@@ -440,7 +481,7 @@ function buildOnyxDataForMoneyRequest(
});
}
- if (!_.isEmpty(optimisticPolicyRecentlyUsedTags)) {
+ if (!isEmptyObject(optimisticPolicyRecentlyUsedTags)) {
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${iouReport.policyID}`,
@@ -448,7 +489,7 @@ function buildOnyxDataForMoneyRequest(
});
}
- if (!_.isEmpty(optimisticPersonalDetailListAction)) {
+ if (!isEmptyObject(optimisticPersonalDetailListAction)) {
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
@@ -456,19 +497,20 @@ function buildOnyxDataForMoneyRequest(
});
}
- const successData = [
- ...(isNewChatReport
- ? [
- {
- onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`,
- value: {
- pendingFields: null,
- errorFields: null,
- },
- },
- ]
- : []),
+ const successData: OnyxUpdate[] = [];
+
+ if (isNewChatReport) {
+ successData.push({
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport?.reportID}`,
+ value: {
+ pendingFields: null,
+ errorFields: null,
+ },
+ });
+ }
+
+ successData.push(
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`,
@@ -488,7 +530,7 @@ function buildOnyxDataForMoneyRequest(
{
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport.reportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport?.reportID}`,
value: {
...(isNewChatReport
? {
@@ -521,17 +563,17 @@ function buildOnyxDataForMoneyRequest(
},
},
},
- ];
+ );
- const failureData = [
+ const failureData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport?.reportID}`,
value: {
- iouReportID: chatReport.iouReportID,
- lastReadTime: chatReport.lastReadTime,
+ iouReportID: chatReport?.iouReportID,
+ lastReadTime: chatReport?.lastReadTime,
pendingFields: null,
- hasOutstandingChildRequest: chatReport.hasOutstandingChildRequest,
+ hasOutstandingChildRequest: chatReport?.hasOutstandingChildRequest,
...(isNewChatReport
? {
errorFields: {
@@ -570,12 +612,14 @@ function buildOnyxDataForMoneyRequest(
{
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport.reportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport?.reportID}`,
value: {
...(isNewChatReport
? {
[chatCreatedAction.reportActionID]: {
- errors: getReceiptError(transaction.receipt, transaction.filename || transaction.receipt.filename, isScanRequest),
+ // Disabling this line since transaction.filename can be an empty string
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
+ errors: getReceiptError(transaction?.receipt, transaction.filename || transaction.receipt?.filename, isScanRequest),
},
[reportPreviewAction.reportActionID]: {
errors: ErrorUtils.getMicroSecondOnyxError(null),
@@ -584,7 +628,9 @@ function buildOnyxDataForMoneyRequest(
: {
[reportPreviewAction.reportActionID]: {
created: reportPreviewAction.created,
- errors: getReceiptError(transaction.receipt, transaction.filename || transaction.receipt.filename, isScanRequest),
+ // Disabling this line since transaction.filename can be an empty string
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
+ errors: getReceiptError(transaction?.receipt, transaction.filename || transaction.receipt?.filename, isScanRequest),
},
}),
},
@@ -596,7 +642,9 @@ function buildOnyxDataForMoneyRequest(
...(shouldCreateNewMoneyRequestReport
? {
[iouCreatedAction.reportActionID]: {
- errors: getReceiptError(transaction.receipt, transaction.filename || transaction.receipt.filename, isScanRequest),
+ // Disabling this line since transaction.filename can be an empty string
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
+ errors: getReceiptError(transaction.receipt, transaction.filename || transaction.receipt?.filename, isScanRequest),
},
[iouAction.reportActionID]: {
errors: ErrorUtils.getMicroSecondOnyxError(null),
@@ -604,7 +652,9 @@ function buildOnyxDataForMoneyRequest(
}
: {
[iouAction.reportActionID]: {
- errors: getReceiptError(transaction.receipt, transaction.filename || transaction.receipt.filename, isScanRequest),
+ // Disabling this line since transaction.filename can be an empty string
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
+ errors: getReceiptError(transaction.receipt, transaction.filename || transaction.receipt?.filename, isScanRequest),
},
}),
},
@@ -612,11 +662,11 @@ function buildOnyxDataForMoneyRequest(
];
// Policy won't be set for P2P cases for which we don't need to compute violations
- if (!policy || !policy.id) {
+ if (!policy?.id) {
return [optimisticData, successData, failureData];
}
- const violationsOnyxData = ViolationsUtils.getViolationsOnyxData(transaction, [], policy.requiresTag, policyTags, policy.requiresCategory, policyCategories);
+ const violationsOnyxData = ViolationsUtils.getViolationsOnyxData(transaction, [], !!policy.requiresTag, policyTags ?? {}, !!policy.requiresCategory, policyCategories ?? {});
if (violationsOnyxData) {
optimisticData.push(violationsOnyxData);
@@ -633,71 +683,39 @@ function buildOnyxDataForMoneyRequest(
/**
* Gathers all the data needed to make a money request. It attempts to find existing reports, iouReports, and receipts. If it doesn't find them, then
* it creates optimistic versions of them and uses those instead
- *
- * @param {Object} parentChatReport
- * @param {Object} participant
- * @param {String} comment
- * @param {Number} amount
- * @param {String} currency
- * @param {String} created
- * @param {String} merchant
- * @param {Number} [payeeAccountID]
- * @param {String} [payeeEmail]
- * @param {Object} [receipt]
- * @param {String} [existingTransactionID]
- * @param {String} [category]
- * @param {String} [tag]
- * @param {Boolean} [billable]
- * @param {Object} [policy]
- * @param {Object} [policyTags]
- * @param {Object} [policyCategories]
- * @param {Number} [moneyRequestReportID] - If user requests money via the report composer on some money request report, we always add a request to that specific report.
- * @returns {Object} data
- * @returns {String} data.payerEmail
- * @returns {Object} data.iouReport
- * @returns {Object} data.chatReport
- * @returns {Object} data.transaction
- * @returns {Object} data.iouAction
- * @returns {Object} data.createdChatReportActionID
- * @returns {Object} data.createdIOUReportActionID
- * @returns {Object} data.reportPreviewAction
- * @returns {Object} data.onyxData
- * @returns {Object} data.onyxData.optimisticData
- * @returns {Object} data.onyxData.successData
- * @returns {Object} data.onyxData.failureData
*/
function getMoneyRequestInformation(
- parentChatReport,
- participant,
- comment,
- amount,
- currency,
- created,
- merchant,
+ parentChatReport: OnyxEntry | EmptyObject,
+ participant: Participant,
+ comment: string,
+ amount: number,
+ currency: string,
+ created: string,
+ merchant: string,
+ receipt: Receipt | undefined,
+ existingTransactionID: string | undefined,
+ category: string | undefined,
+ tag: string | undefined,
+ billable: boolean | undefined,
+ policy: OnyxTypes.Policy | EmptyObject | undefined,
+ policyTags: OnyxTypes.PolicyTags | undefined,
+ policyCategories: OnyxTypes.PolicyCategories | undefined,
payeeAccountID = userAccountID,
payeeEmail = currentUserEmail,
- receipt = undefined,
- existingTransactionID = undefined,
- category = undefined,
- tag = undefined,
- billable = undefined,
- policy = undefined,
- policyTags = undefined,
- policyCategories = undefined,
- moneyRequestReportID = 0,
-) {
- const payerEmail = OptionsListUtils.addSMSDomainIfPhoneNumber(participant.login);
+ moneyRequestReportID = '',
+): MoneyRequestInformation {
+ const payerEmail = OptionsListUtils.addSMSDomainIfPhoneNumber(participant.login ?? '');
const payerAccountID = Number(participant.accountID);
const isPolicyExpenseChat = participant.isPolicyExpenseChat;
// STEP 1: Get existing chat report OR build a new optimistic one
let isNewChatReport = false;
- let chatReport = lodashGet(parentChatReport, 'reportID', null) ? parentChatReport : null;
+ let chatReport = !isEmptyObject(parentChatReport) && parentChatReport?.reportID ? parentChatReport : null;
// If this is a policyExpenseChat, the chatReport must exist and we can get it from Onyx.
// report is null if the flow is initiated from the global create menu. However, participant always stores the reportID if it exists, which is the case for policyExpenseChats
if (!chatReport && isPolicyExpenseChat) {
- chatReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${participant.reportID}`];
+ chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${participant.reportID}`] ?? null;
}
if (!chatReport) {
@@ -712,22 +730,22 @@ function getMoneyRequestInformation(
// STEP 2: Get the money request report. If the moneyRequestReportID has been provided, we want to add the transaction to this specific report.
// If no such reportID has been provided, let's use the chatReport.iouReportID property. In case that is not present, build a new optimistic money request report.
- let iouReport = null;
+ let iouReport: OnyxEntry = null;
const shouldCreateNewMoneyRequestReport = !moneyRequestReportID && (!chatReport.iouReportID || ReportUtils.hasIOUWaitingOnCurrentUserBankAccount(chatReport));
- if (moneyRequestReportID > 0) {
- iouReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${moneyRequestReportID}`];
+ if (moneyRequestReportID) {
+ iouReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${moneyRequestReportID}`] ?? null;
} else if (!shouldCreateNewMoneyRequestReport) {
- iouReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${chatReport.iouReportID}`];
+ iouReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${chatReport.iouReportID}`] ?? null;
}
// Check if the Scheduled Submit is enabled in case of expense report
let needsToBeManuallySubmitted = true;
let isFromPaidPolicy = false;
if (isPolicyExpenseChat) {
- isFromPaidPolicy = PolicyUtils.isPaidGroupPolicy(policy);
+ isFromPaidPolicy = PolicyUtils.isPaidGroupPolicy(policy ?? null);
// If the scheduled submit is turned off on the policy, user needs to manually submit the report which is indicated by GBR in LHN
- needsToBeManuallySubmitted = isFromPaidPolicy && !(lodashGet(policy, 'harvesting.enabled', policy.isHarvestingEnabled) || false);
+ needsToBeManuallySubmitted = isFromPaidPolicy && !(policy?.harvesting?.enabled ?? policy?.isHarvestingEnabled);
// If the linked expense report on paid policy is not draft, we need to create a new draft expense report
if (iouReport && isFromPaidPolicy && !ReportUtils.isDraftExpenseReport(iouReport)) {
@@ -738,7 +756,7 @@ function getMoneyRequestInformation(
if (iouReport) {
if (isPolicyExpenseChat) {
iouReport = {...iouReport};
- if (lodashGet(iouReport, 'currency') === currency) {
+ if (iouReport?.currency === currency && typeof iouReport.total === 'number') {
// Because of the Expense reports are stored as negative values, we substract the total from the amount
iouReport.total -= amount;
}
@@ -747,16 +765,16 @@ function getMoneyRequestInformation(
}
} else {
iouReport = isPolicyExpenseChat
- ? ReportUtils.buildOptimisticExpenseReport(chatReport.reportID, chatReport.policyID, payeeAccountID, amount, currency)
+ ? ReportUtils.buildOptimisticExpenseReport(chatReport.reportID, chatReport.policyID ?? '', payeeAccountID, amount, currency)
: ReportUtils.buildOptimisticIOUReport(payeeAccountID, payerAccountID, amount, chatReport.reportID, currency);
}
// STEP 3: Build optimistic receipt and transaction
- const receiptObject = {};
+ const receiptObject: Receipt = {};
let filename;
- if (receipt && receipt.source) {
+ if (receipt?.source) {
receiptObject.source = receipt.source;
- receiptObject.state = receipt.state || CONST.IOU.RECEIPT_STATE.SCANREADY;
+ receiptObject.state = receipt.state ?? CONST.IOU.RECEIPT_STATE.SCANREADY;
filename = receipt.name;
}
let optimisticTransaction = TransactionUtils.buildOptimisticTransaction(
@@ -787,7 +805,7 @@ function getMoneyRequestInformation(
// to remind me to do this.
const existingTransaction = allTransactionDrafts[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${CONST.IOU.OPTIMISTIC_TRANSACTION_ID}`];
if (existingTransaction && existingTransaction.iouRequestType === CONST.IOU.REQUEST_TYPE.DISTANCE) {
- optimisticTransaction = fastMerge(existingTransaction, optimisticTransaction);
+ optimisticTransaction = fastMerge(existingTransaction, optimisticTransaction, false);
}
// STEP 4: Build optimistic reportActions. We need:
@@ -806,7 +824,7 @@ function getMoneyRequestInformation(
comment,
[participant],
optimisticTransaction.transactionID,
- '',
+ undefined,
iouReport.reportID,
false,
false,
@@ -833,12 +851,14 @@ function getMoneyRequestInformation(
[payerAccountID]: {
accountID: payerAccountID,
avatar: UserUtils.getDefaultAvatarURL(payerAccountID),
+ // Disabling this line since participant.displayName can be an empty string
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
displayName: LocalePhoneNumber.formatPhoneNumber(participant.displayName || payerEmail),
login: participant.login,
isOptimisticPersonalDetail: true,
},
}
- : undefined;
+ : {};
// STEP 5: Build Onyx Data
const [optimisticData, successData, failureData] = buildOnyxDataForMoneyRequest(
@@ -867,8 +887,8 @@ function getMoneyRequestInformation(
chatReport,
transaction: optimisticTransaction,
iouAction,
- createdChatReportActionID: isNewChatReport ? optimisticCreatedActionForChat.reportActionID : 0,
- createdIOUReportActionID: shouldCreateNewMoneyRequestReport ? optimisticCreatedActionForIOU.reportActionID : 0,
+ createdChatReportActionID: isNewChatReport ? optimisticCreatedActionForChat.reportActionID : '0',
+ createdIOUReportActionID: shouldCreateNewMoneyRequestReport ? optimisticCreatedActionForIOU.reportActionID : '0',
reportPreviewAction,
onyxData: {
optimisticData,
@@ -878,33 +898,31 @@ function getMoneyRequestInformation(
};
}
-/**
- * Requests money based on a distance (eg. mileage from a map)
- *
- * @param {Object} report
- * @param {Object} participant
- * @param {String} comment
- * @param {String} created
- * @param {String} [category]
- * @param {String} [tag]
- * @param {Number} amount
- * @param {String} currency
- * @param {String} merchant
- * @param {Boolean} [billable]
- * @param {Object} validWaypoints
- * @param {Object} policy - May be undefined, an empty object, or an object matching the Policy type (src/types/onyx/Policy.ts)
- * @param {Array} policyTags
- * @param {Array} policyCategories
- */
-function createDistanceRequest(report, participant, comment, created, category, tag, amount, currency, merchant, billable, validWaypoints, policy, policyTags, policyCategories) {
+/** Requests money based on a distance (eg. mileage from a map) */
+function createDistanceRequest(
+ report: OnyxTypes.Report,
+ participant: Participant,
+ comment: string,
+ created: string,
+ category: string | undefined,
+ tag: string | undefined,
+ amount: number,
+ currency: string,
+ merchant: string,
+ billable: boolean | undefined,
+ validWaypoints: WaypointCollection,
+ policy: OnyxTypes.Policy | EmptyObject | undefined,
+ policyTags: OnyxTypes.PolicyTags,
+ policyCategories: OnyxTypes.PolicyCategories,
+) {
// If the report is an iou or expense report, we should get the linked chat report to be passed to the getMoneyRequestInformation function
const isMoneyRequestReport = ReportUtils.isMoneyRequestReport(report);
const currentChatReport = isMoneyRequestReport ? ReportUtils.getReport(report.chatReportID) : report;
- const moneyRequestReportID = isMoneyRequestReport ? report.reportID : 0;
+ const moneyRequestReportID = isMoneyRequestReport ? report.reportID : '';
const currentCreated = DateUtils.enrichMoneyRequestTimestamp(created);
- const optimisticReceipt = {
- source: ReceiptGeneric,
+ const optimisticReceipt: Receipt = {
+ source: ReceiptGeneric as ReceiptSource,
state: CONST.IOU.RECEIPT_STATE.OPEN,
};
const {iouReport, chatReport, transaction, iouAction, createdChatReportActionID, createdIOUReportActionID, reportPreviewAction, onyxData} = getMoneyRequestInformation(
@@ -915,8 +933,6 @@ function createDistanceRequest(report, participant, comment, created, category,
currency,
currentCreated,
merchant,
- userAccountID,
- currentUserEmail,
optimisticReceipt,
undefined,
category,
@@ -925,71 +941,76 @@ function createDistanceRequest(report, participant, comment, created, category,
policy,
policyTags,
policyCategories,
+ userAccountID,
+ currentUserEmail,
moneyRequestReportID,
);
- API.write(
- 'CreateDistanceRequest',
- {
- comment,
- iouReportID: iouReport.reportID,
- chatReportID: chatReport.reportID,
- transactionID: transaction.transactionID,
- reportActionID: iouAction.reportActionID,
- createdChatReportActionID,
- createdIOUReportActionID,
- reportPreviewReportActionID: reportPreviewAction.reportActionID,
- waypoints: JSON.stringify(validWaypoints),
- created: currentCreated,
- category,
- tag,
- billable,
- },
- onyxData,
- );
+
+ const parameters: CreateDistanceRequestParams = {
+ comment,
+ iouReportID: iouReport.reportID,
+ chatReportID: chatReport.reportID,
+ transactionID: transaction.transactionID,
+ reportActionID: iouAction.reportActionID,
+ createdChatReportActionID,
+ createdIOUReportActionID,
+ reportPreviewReportActionID: reportPreviewAction.reportActionID,
+ waypoints: JSON.stringify(validWaypoints),
+ created: currentCreated,
+ category,
+ tag,
+ billable,
+ };
+
+ API.write(WRITE_COMMANDS.CREATE_DISTANCE_REQUEST, parameters, onyxData);
Navigation.dismissModal(isMoneyRequestReport ? report.reportID : chatReport.reportID);
Report.notifyNewAction(chatReport.reportID, userAccountID);
}
/**
- * @param {String} transactionID
- * @param {String} transactionThreadReportID
- * @param {Object} transactionChanges
- * @param {String} [transactionChanges.created] Present when updated the date field
- * @param {Boolean} onlyIncludeChangedFields
- * When 'true', then the returned params will only include the transaction details for the fields that were changed.
- * When `false`, then the returned params will include all the transaction details, regardless of which fields were changed.
- * This setting is necessary while the UpdateDistanceRequest API is refactored to be fully 1:1:1 in https://github.com/Expensify/App/issues/28358
- * @returns {object}
- */
-function getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, transactionChanges, onlyIncludeChangedFields) {
- const optimisticData = [];
- const successData = [];
- const failureData = [];
+ * @param transactionChanges
+ * @param [transactionChanges.created] Present when updated the date field
+ * @param onlyIncludeChangedFields
+ * When 'true', then the returned params will only include the transaction details for the fields that were changed.
+ * When `false`, then the returned params will include all the transaction details, regardless of which fields were changed.
+ * This setting is necessary while the UpdateDistanceRequest API is refactored to be fully 1:1:1 in https://github.com/Expensify/App/issues/28358
+ */
+function getUpdateMoneyRequestParams(
+ transactionID: string,
+ transactionThreadReportID: string,
+ transactionChanges: TransactionChanges,
+ onlyIncludeChangedFields: boolean,
+): UpdateMoneyRequestData {
+ const optimisticData: OnyxUpdate[] = [];
+ const successData: OnyxUpdate[] = [];
+ const failureData: OnyxUpdate[] = [];
// Step 1: Set any "pending fields" (ones updated while the user was offline) to have error messages in the failureData
- const pendingFields = _.mapObject(transactionChanges, () => CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE);
- const clearedPendingFields = _.mapObject(transactionChanges, () => null);
- const errorFields = _.mapObject(pendingFields, () => ({
- [DateUtils.getMicroseconds()]: Localize.translateLocal('iou.error.genericEditFailureMessage'),
- }));
+ const pendingFields = Object.fromEntries(Object.keys(transactionChanges).map((key) => [key, CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE]));
+ const clearedPendingFields = Object.fromEntries(Object.keys(transactionChanges).map((key) => [key, null]));
+ const errorFields = Object.fromEntries(Object.keys(pendingFields).map((key) => [key, {[DateUtils.getMicroseconds()]: Localize.translateLocal('iou.error.genericEditFailureMessage')}]));
// Step 2: Get all the collections being updated
- const transactionThread = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`];
- const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`];
- const iouReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThread.parentReportID}`];
+ const transactionThread = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`] ?? null;
+ const transaction = allTransactions?.[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`];
+ const iouReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionThread?.parentReportID}`] ?? null;
const isFromExpenseReport = ReportUtils.isExpenseReport(iouReport);
const isScanning = TransactionUtils.hasReceipt(transaction) && TransactionUtils.isReceiptBeingScanned(transaction);
- const updatedTransaction = TransactionUtils.getUpdatedTransaction(transaction, transactionChanges, isFromExpenseReport);
+ const updatedTransaction = transaction ? TransactionUtils.getUpdatedTransaction(transaction, transactionChanges, isFromExpenseReport) : null;
const transactionDetails = ReportUtils.getTransactionDetails(updatedTransaction);
- // This needs to be a JSON string since we're sending this to the MapBox API
- transactionDetails.waypoints = JSON.stringify(transactionDetails.waypoints);
+ if (transactionDetails?.waypoints) {
+ // This needs to be a JSON string since we're sending this to the MapBox API
+ transactionDetails.waypoints = JSON.stringify(transactionDetails.waypoints);
+ }
- const dataToIncludeInParams = onlyIncludeChangedFields ? _.pick(transactionDetails, _.keys(transactionChanges)) : transactionDetails;
+ const dataToIncludeInParams: Partial | undefined = onlyIncludeChangedFields
+ ? Object.fromEntries(Object.entries(transactionDetails ?? {}).filter(([key]) => Object.keys(transactionChanges).includes(key)))
+ : transactionDetails;
- const params = {
+ const params: UpdateMoneyRequestParams = {
...dataToIncludeInParams,
- reportID: iouReport.reportID,
+ reportID: iouReport?.reportID,
transactionID,
};
@@ -997,30 +1018,30 @@ function getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, t
// We don't create a modified report action if we're updating the waypoints,
// since there isn't actually any optimistic data we can create for them and the report action is created on the server
// with the response from the MapBox API
- if (!_.has(transactionChanges, 'waypoints')) {
+ if (!('waypoints' in transactionChanges)) {
const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges, isFromExpenseReport);
params.reportActionID = updatedReportAction.reportActionID;
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread.reportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread?.reportID}`,
value: {
- [updatedReportAction.reportActionID]: updatedReportAction,
+ [updatedReportAction.reportActionID]: updatedReportAction as OnyxTypes.ReportAction,
},
});
successData.push({
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread.reportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread?.reportID}`,
value: {
[updatedReportAction.reportActionID]: {pendingAction: null},
},
});
failureData.push({
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread.reportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread?.reportID}`,
value: {
[updatedReportAction.reportActionID]: {
- ...updatedReportAction,
+ ...(updatedReportAction as OnyxTypes.ReportAction),
errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericEditFailureMessage'),
},
},
@@ -1030,23 +1051,25 @@ function getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, t
// Should only update if the transaction matches the currency of the report, else we wait for the update
// from the server with the currency conversion
let updatedMoneyRequestReport = {...iouReport};
- if (updatedTransaction.currency === iouReport.currency && updatedTransaction.modifiedAmount) {
+ if (updatedTransaction?.currency === iouReport?.currency && updatedTransaction?.modifiedAmount) {
const diff = TransactionUtils.getAmount(transaction, true) - TransactionUtils.getAmount(updatedTransaction, true);
- if (ReportUtils.isExpenseReport(iouReport)) {
+ if (ReportUtils.isExpenseReport(iouReport) && typeof updatedMoneyRequestReport.total === 'number') {
updatedMoneyRequestReport.total += diff;
} else {
- updatedMoneyRequestReport = IOUUtils.updateIOUOwnerAndTotal(iouReport, updatedReportAction.actorAccountID, diff, TransactionUtils.getCurrency(transaction), false);
+ updatedMoneyRequestReport = iouReport
+ ? IOUUtils.updateIOUOwnerAndTotal(iouReport, updatedReportAction.actorAccountID ?? -1, diff, TransactionUtils.getCurrency(transaction), false)
+ : {};
}
updatedMoneyRequestReport.cachedTotal = CurrencyUtils.convertToDisplayString(updatedMoneyRequestReport.total, updatedTransaction.currency);
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport?.reportID}`,
value: updatedMoneyRequestReport,
});
successData.push({
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport?.reportID}`,
value: {pendingAction: null},
});
}
@@ -1059,54 +1082,53 @@ function getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, t
value: {
...updatedTransaction,
pendingFields,
- isLoading: _.has(transactionChanges, 'waypoints'),
+ isLoading: 'waypoints' in transactionChanges,
errorFields: null,
},
});
- if (isScanning && (_.has(transactionChanges, 'amount') || _.has(transactionChanges, 'currency'))) {
+ if (isScanning && ('amount' in transactionChanges || 'currency' in transactionChanges)) {
optimisticData.push(
- ...[
- {
- onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.reportID}`,
- value: {
- [transactionThread.parentReportActionID]: {
- whisperedToAccountIDs: [],
- },
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport?.reportID}`,
+ value: {
+ [transactionThread?.parentReportActionID ?? '']: {
+ whisperedToAccountIDs: [],
},
},
- {
- onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.parentReportID}`,
- value: {
- [iouReport.parentReportActionID]: {
- whisperedToAccountIDs: [],
- },
+ },
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport?.parentReportID}`,
+ value: {
+ [iouReport?.parentReportActionID ?? '']: {
+ whisperedToAccountIDs: [],
},
},
- ],
+ },
);
}
+
// Update recently used categories if the category is changed
- if (_.has(transactionChanges, 'category')) {
- const optimisticPolicyRecentlyUsedCategories = Policy.buildOptimisticPolicyRecentlyUsedCategories(iouReport.policyID, transactionChanges.category);
- if (!_.isEmpty(optimisticPolicyRecentlyUsedCategories)) {
+ if ('category' in transactionChanges) {
+ const optimisticPolicyRecentlyUsedCategories = Policy.buildOptimisticPolicyRecentlyUsedCategories(iouReport?.policyID, transactionChanges.category);
+ if (optimisticPolicyRecentlyUsedCategories.length) {
optimisticData.push({
onyxMethod: Onyx.METHOD.SET,
- key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES}${iouReport.policyID}`,
+ key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES}${iouReport?.policyID}`,
value: optimisticPolicyRecentlyUsedCategories,
});
}
}
// Update recently used categories if the tag is changed
- if (_.has(transactionChanges, 'tag')) {
- const optimisticPolicyRecentlyUsedTags = Policy.buildOptimisticPolicyRecentlyUsedTags(iouReport.policyID, transactionChanges.tag);
- if (!_.isEmpty(optimisticPolicyRecentlyUsedTags)) {
+ if ('tag' in transactionChanges) {
+ const optimisticPolicyRecentlyUsedTags = Policy.buildOptimisticPolicyRecentlyUsedTags(iouReport?.policyID, transactionChanges.tag);
+ if (!isEmptyObject(optimisticPolicyRecentlyUsedTags)) {
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${iouReport.policyID}`,
+ key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${iouReport?.policyID}`,
value: optimisticPolicyRecentlyUsedTags,
});
}
@@ -1123,7 +1145,7 @@ function getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, t
},
});
- if (_.has(transactionChanges, 'waypoints')) {
+ if ('waypoints' in transactionChanges) {
// Delete the draft transaction when editing waypoints when the server responds successfully and there are no errors
successData.push({
onyxMethod: Onyx.METHOD.SET,
@@ -1143,12 +1165,14 @@ function getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, t
},
});
- // Reset the iouReport to it's original state
- failureData.push({
- onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`,
- value: iouReport,
- });
+ if (iouReport) {
+ // Reset the iouReport to it's original state
+ failureData.push({
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`,
+ value: iouReport,
+ });
+ }
return {
params,
@@ -1156,166 +1180,95 @@ function getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, t
};
}
-/**
- * Updates the created date of a money request
- *
- * @param {String} transactionID
- * @param {String} transactionThreadReportID
- * @param {String} val
- */
-function updateMoneyRequestDate(transactionID, transactionThreadReportID, val) {
- const transactionChanges = {
- created: val,
+/** Updates the created date of a money request */
+function updateMoneyRequestDate(transactionID: string, transactionThreadReportID: string, value: string) {
+ const transactionChanges: TransactionChanges = {
+ created: value,
};
const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, transactionChanges, true);
- API.write('UpdateMoneyRequestDate', params, onyxData);
+ API.write(WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DATE, params, onyxData);
}
-/**
- * Updates the billable field of a money request
- *
- * @param {String} transactionID
- * @param {Number} transactionThreadReportID
- * @param {String} val
- */
-function updateMoneyRequestBillable(transactionID, transactionThreadReportID, val) {
- const transactionChanges = {
- billable: val,
+/** Updates the billable field of a money request */
+function updateMoneyRequestBillable(transactionID: string, transactionThreadReportID: string, value: boolean) {
+ const transactionChanges: TransactionChanges = {
+ billable: value,
};
const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, transactionChanges, true);
- API.write('UpdateMoneyRequestBillable', params, onyxData);
+ API.write(WRITE_COMMANDS.UPDATE_MONEY_REQUEST_BILLABLE, params, onyxData);
}
-/**
- * Updates the merchant field of a money request
- *
- * @param {String} transactionID
- * @param {Number} transactionThreadReportID
- * @param {String} val
- */
-function updateMoneyRequestMerchant(transactionID, transactionThreadReportID, val) {
- const transactionChanges = {
- merchant: val,
+/** Updates the merchant field of a money request */
+function updateMoneyRequestMerchant(transactionID: string, transactionThreadReportID: string, value: string) {
+ const transactionChanges: TransactionChanges = {
+ merchant: value,
};
const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, transactionChanges, true);
- API.write('UpdateMoneyRequestMerchant', params, onyxData);
+ API.write(WRITE_COMMANDS.UPDATE_MONEY_REQUEST_MERCHANT, params, onyxData);
}
-/**
- * Updates the tag of a money request
- *
- * @param {String} transactionID
- * @param {Number} transactionThreadReportID
- * @param {String} tag
- */
-function updateMoneyRequestTag(transactionID, transactionThreadReportID, tag) {
- const transactionChanges = {
+/** Updates the tag of a money request */
+function updateMoneyRequestTag(transactionID: string, transactionThreadReportID: string, tag: string) {
+ const transactionChanges: TransactionChanges = {
tag,
};
const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, transactionChanges, true);
- API.write('UpdateMoneyRequestTag', params, onyxData);
+ API.write(WRITE_COMMANDS.UPDATE_MONEY_REQUEST_TAG, params, onyxData);
}
-/**
- * Updates the waypoints of a distance money request
- *
- * @param {String} transactionID
- * @param {Number} transactionThreadReportID
- * @param {Object} waypoints
- */
-function updateMoneyRequestDistance(transactionID, transactionThreadReportID, waypoints) {
- const transactionChanges = {
+/** Updates the waypoints of a distance money request */
+function updateMoneyRequestDistance(transactionID: string, transactionThreadReportID: string, waypoints: WaypointCollection) {
+ const transactionChanges: TransactionChanges = {
waypoints,
};
const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, transactionChanges, true);
- API.write('UpdateMoneyRequestDistance', params, onyxData);
+ API.write(WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DISTANCE, params, onyxData);
}
-/**
- * Updates the category of a money request
- *
- * @param {String} transactionID
- * @param {Number} transactionThreadReportID
- * @param {String} category
- */
-function updateMoneyRequestCategory(transactionID, transactionThreadReportID, category) {
- const transactionChanges = {
+/** Updates the category of a money request */
+function updateMoneyRequestCategory(transactionID: string, transactionThreadReportID: string, category: string) {
+ const transactionChanges: TransactionChanges = {
category,
};
const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, transactionChanges, true);
- API.write('UpdateMoneyRequestCategory', params, onyxData);
+ API.write(WRITE_COMMANDS.UPDATE_MONEY_REQUEST_CATEGORY, params, onyxData);
}
-/**
- * Updates the description of a money request
- *
- * @param {String} transactionID
- * @param {Number} transactionThreadReportID
- * @param {String} comment
- */
-function updateMoneyRequestDescription(transactionID, transactionThreadReportID, comment) {
- const transactionChanges = {
+/** Updates the description of a money request */
+function updateMoneyRequestDescription(transactionID: string, transactionThreadReportID: string, comment: string) {
+ const transactionChanges: TransactionChanges = {
comment,
};
const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, transactionChanges, true);
- API.write('UpdateMoneyRequestDescription', params, onyxData);
+ API.write(WRITE_COMMANDS.UPDATE_MONEY_REQUEST_DESCRIPTION, params, onyxData);
}
-/**
- * Edits an existing distance request
- *
- * @param {String} transactionID
- * @param {String} transactionThreadReportID
- * @param {Object} transactionChanges
- * @param {String} [transactionChanges.created]
- * @param {Number} [transactionChanges.amount]
- * @param {Object} [transactionChanges.comment]
- * @param {Object} [transactionChanges.waypoints]
- *
- */
-function updateDistanceRequest(transactionID, transactionThreadReportID, transactionChanges) {
+/** Edits an existing distance request */
+function updateDistanceRequest(transactionID: string, transactionThreadReportID: string, transactionChanges: TransactionChanges) {
const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, transactionChanges, false);
- API.write('UpdateDistanceRequest', params, onyxData);
+ API.write(WRITE_COMMANDS.UPDATE_DISTANCE_REQUEST, params, onyxData);
}
/**
* Request money from another user
- *
- * @param {Object} report
- * @param {Number} amount - always in the smallest unit of the currency
- * @param {String} currency
- * @param {String} created
- * @param {String} merchant
- * @param {String} payeeEmail
- * @param {Number} payeeAccountID
- * @param {Object} participant
- * @param {String} comment
- * @param {Object} [receipt]
- * @param {String} [category]
- * @param {String} [tag]
- * @param {String} [taxCode]
- * @param {Number} [taxAmount]
- * @param {Boolean} [billable]
- * @param {Object} [policy]
- * @param {Object} [policyTags]
- * @param {Object} [policyCategories]
+ * @param amount - always in the smallest unit of the currency
*/
function requestMoney(
- report,
- amount,
- currency,
- created,
- merchant,
- payeeEmail,
- payeeAccountID,
- participant,
- comment,
- receipt = undefined,
- category = undefined,
- tag = undefined,
+ report: OnyxTypes.Report,
+ amount: number,
+ currency: string,
+ created: string,
+ merchant: string,
+ payeeEmail: string,
+ payeeAccountID: number,
+ participant: Participant,
+ comment: string,
+ receipt: Receipt,
+ category?: string,
+ tag?: string,
taxCode = '',
taxAmount = 0,
- billable = undefined,
+ billable?: boolean,
policy = undefined,
policyTags = undefined,
policyCategories = undefined,
@@ -1323,7 +1276,7 @@ function requestMoney(
// If the report is iou or expense report, we should get the linked chat report to be passed to the getMoneyRequestInformation function
const isMoneyRequestReport = ReportUtils.isMoneyRequestReport(report);
const currentChatReport = isMoneyRequestReport ? ReportUtils.getReport(report.chatReportID) : report;
- const moneyRequestReportID = isMoneyRequestReport ? report.reportID : 0;
+ const moneyRequestReportID = isMoneyRequestReport ? report.reportID : '';
const currentCreated = DateUtils.enrichMoneyRequestTimestamp(created);
const {payerAccountID, payerEmail, iouReport, chatReport, transaction, iouAction, createdChatReportActionID, createdIOUReportActionID, reportPreviewAction, onyxData} =
getMoneyRequestInformation(
@@ -1334,8 +1287,6 @@ function requestMoney(
currency,
currentCreated,
merchant,
- payeeAccountID,
- payeeEmail,
receipt,
undefined,
category,
@@ -1344,37 +1295,37 @@ function requestMoney(
policy,
policyTags,
policyCategories,
+ payeeAccountID,
+ payeeEmail,
moneyRequestReportID,
);
const activeReportID = isMoneyRequestReport ? report.reportID : chatReport.reportID;
- API.write(
- 'RequestMoney',
- {
- debtorEmail: payerEmail,
- debtorAccountID: payerAccountID,
- amount,
- currency,
- comment,
- created: currentCreated,
- merchant,
- iouReportID: iouReport.reportID,
- chatReportID: chatReport.reportID,
- transactionID: transaction.transactionID,
- reportActionID: iouAction.reportActionID,
- createdChatReportActionID,
- createdIOUReportActionID,
- reportPreviewReportActionID: reportPreviewAction.reportActionID,
- receipt,
- receiptState: lodashGet(receipt, 'state'),
- category,
- tag,
- taxCode,
- taxAmount,
- billable,
- },
- onyxData,
- );
+ const parameters: RequestMoneyParams = {
+ debtorEmail: payerEmail,
+ debtorAccountID: payerAccountID,
+ amount,
+ currency,
+ comment,
+ created: currentCreated,
+ merchant,
+ iouReportID: iouReport.reportID,
+ chatReportID: chatReport.reportID,
+ transactionID: transaction.transactionID,
+ reportActionID: iouAction.reportActionID,
+ createdChatReportActionID,
+ createdIOUReportActionID,
+ reportPreviewReportActionID: reportPreviewAction.reportActionID,
+ receipt,
+ receiptState: receipt?.state,
+ category,
+ tag,
+ taxCode,
+ taxAmount,
+ billable,
+ };
+
+ API.write(WRITE_COMMANDS.REQUEST_MONEY, parameters, onyxData);
resetMoneyRequestInfo();
Navigation.dismissModal(activeReportID);
Report.notifyNewAction(activeReportID, payeeAccountID);
@@ -1391,29 +1342,30 @@ function requestMoney(
* {email: 'user2', amount: 100, iouReportID: '100', chatReportID: '110', transactionID: '120', reportActionID: '130'},
* {email: 'user3', amount: 100, iouReportID: '200', chatReportID: '210', transactionID: '220', reportActionID: '230'}
* ]
- * @param {Array} participants
- * @param {String} currentUserLogin
- * @param {Number} currentUserAccountID
- * @param {Number} amount - always in the smallest unit of the currency
- * @param {String} comment
- * @param {String} currency
- * @param {String} merchant
- * @param {String} category
- * @param {String} tag
- * @param {String} existingSplitChatReportID - the report ID where the split bill happens, could be a group chat or a workspace chat
- * @param {Boolean} billable
- *
- * @return {Object}
- */
-function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAccountID, amount, comment, currency, merchant, category, tag, existingSplitChatReportID = '', billable = false) {
+ * @param amount - always in the smallest unit of the currency
+ * @param existingSplitChatReportID - the report ID where the split bill happens, could be a group chat or a workspace chat
+ */
+function createSplitsAndOnyxData(
+ participants: Participant[],
+ currentUserLogin: string,
+ currentUserAccountID: number,
+ amount: number,
+ comment: string,
+ currency: string,
+ merchant: string,
+ category: string,
+ tag: string,
+ existingSplitChatReportID = '',
+ billable = false,
+): SplitsAndOnyxData {
const currentUserEmailForIOUSplit = OptionsListUtils.addSMSDomainIfPhoneNumber(currentUserLogin);
- const participantAccountIDs = _.map(participants, (participant) => Number(participant.accountID));
+ const participantAccountIDs = participants.map((participant) => Number(participant.accountID));
const existingSplitChatReport =
existingSplitChatReportID || participants[0].reportID
- ? allReports[`${ONYXKEYS.COLLECTION.REPORT}${existingSplitChatReportID || participants[0].reportID}`]
+ ? allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${existingSplitChatReportID || participants[0].reportID}`]
: ReportUtils.getChatByParticipants(participantAccountIDs);
- const splitChatReport = existingSplitChatReport || ReportUtils.buildOptimisticChatReport(participantAccountIDs);
- const isOwnPolicyExpenseChat = splitChatReport.isOwnPolicyExpenseChat;
+ const splitChatReport = existingSplitChatReport ?? ReportUtils.buildOptimisticChatReport(participantAccountIDs);
+ const isOwnPolicyExpenseChat = !!splitChatReport.isOwnPolicyExpenseChat;
const splitTransaction = TransactionUtils.buildOptimisticTransaction(
amount,
@@ -1441,7 +1393,7 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco
comment,
participants,
splitTransaction.transactionID,
- '',
+ undefined,
'',
false,
false,
@@ -1450,8 +1402,8 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco
);
splitChatReport.lastReadTime = DateUtils.getDBTime();
- splitChatReport.lastMessageText = splitIOUReportAction.message[0].text;
- splitChatReport.lastMessageHtml = splitIOUReportAction.message[0].html;
+ splitChatReport.lastMessageText = splitIOUReportAction.message?.[0].text;
+ splitChatReport.lastMessageHtml = splitIOUReportAction.message?.[0].html;
// If we have an existing splitChatReport (group chat or workspace) use it's pending fields, otherwise indicate that we are adding a chat
if (!existingSplitChatReport) {
@@ -1460,7 +1412,7 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco
};
}
- const optimisticData = [
+ const optimisticData: OnyxUpdate[] = [
{
// Use set for new reports because it doesn't exist yet, is faster,
// and we need the data to be available when we navigate to the chat page
@@ -1468,14 +1420,22 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco
key: `${ONYXKEYS.COLLECTION.REPORT}${splitChatReport.reportID}`,
value: splitChatReport,
},
- {
- onyxMethod: existingSplitChatReport ? Onyx.METHOD.MERGE : Onyx.METHOD.SET,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${splitChatReport.reportID}`,
- value: {
- ...(existingSplitChatReport ? {} : {[splitCreatedReportAction.reportActionID]: splitCreatedReportAction}),
- [splitIOUReportAction.reportActionID]: splitIOUReportAction,
- },
- },
+ existingSplitChatReport
+ ? {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${splitChatReport.reportID}`,
+ value: {
+ [splitIOUReportAction.reportActionID]: splitIOUReportAction as OnyxTypes.ReportAction,
+ },
+ }
+ : {
+ onyxMethod: Onyx.METHOD.SET,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${splitChatReport.reportID}`,
+ value: {
+ [splitCreatedReportAction.reportActionID]: splitCreatedReportAction as OnyxTypes.ReportAction,
+ [splitIOUReportAction.reportActionID]: splitIOUReportAction as OnyxTypes.ReportAction,
+ },
+ },
{
onyxMethod: Onyx.METHOD.SET,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${splitTransaction.transactionID}`,
@@ -1483,7 +1443,7 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco
},
];
- const successData = [
+ const successData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${splitChatReport.reportID}`,
@@ -1512,7 +1472,7 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco
});
}
- const failureData = [
+ const failureData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${splitTransaction.transactionID}`,
@@ -1562,16 +1522,16 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco
// Loop through participants creating individual chats, iouReports and reportActionIDs as needed
const splitAmount = IOUUtils.calculateAmount(participants.length, amount, currency, false);
- const splits = [{email: currentUserEmailForIOUSplit, accountID: currentUserAccountID, amount: IOUUtils.calculateAmount(participants.length, amount, currency, true)}];
+ const splits: Split[] = [{email: currentUserEmailForIOUSplit, accountID: currentUserAccountID, amount: IOUUtils.calculateAmount(participants.length, amount, currency, true)}];
const hasMultipleParticipants = participants.length > 1;
- _.each(participants, (participant) => {
+ participants.forEach((participant) => {
// In a case when a participant is a workspace, even when a current user is not an owner of the workspace
const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(participant);
// In case the participant is a workspace, email & accountID should remain undefined and won't be used in the rest of this code
// participant.login is undefined when the request is initiated from a group DM with an unknown user, so we need to add a default
- const email = isOwnPolicyExpenseChat || isPolicyExpenseChat ? '' : OptionsListUtils.addSMSDomainIfPhoneNumber(participant.login || '').toLowerCase();
+ const email = isOwnPolicyExpenseChat || isPolicyExpenseChat ? '' : OptionsListUtils.addSMSDomainIfPhoneNumber(participant.login ?? '').toLowerCase();
const accountID = isOwnPolicyExpenseChat || isPolicyExpenseChat ? 0 : Number(participant.accountID);
if (email === currentUserEmailForIOUSplit) {
return;
@@ -1579,10 +1539,10 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco
// STEP 1: Get existing chat report OR build a new optimistic one
// If we only have one participant and the request was initiated from the global create menu, i.e. !existingGroupChatReportID, the oneOnOneChatReport is the groupChatReport
- let oneOnOneChatReport;
+ let oneOnOneChatReport: OptimisticChatReport;
let isNewOneOnOneChatReport = false;
let shouldCreateOptimisticPersonalDetails = false;
- const personalDetailExists = lodashHas(allPersonalDetails, accountID);
+ const personalDetailExists = accountID in allPersonalDetails;
// If this is a split between two people only and the function
// wasn't provided with an existing group chat report id
@@ -1596,22 +1556,24 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco
const existingChatReport = ReportUtils.getChatByParticipants([accountID]);
isNewOneOnOneChatReport = !existingChatReport;
shouldCreateOptimisticPersonalDetails = isNewOneOnOneChatReport && !personalDetailExists;
- oneOnOneChatReport = existingChatReport || ReportUtils.buildOptimisticChatReport([accountID]);
+ oneOnOneChatReport = existingChatReport ?? ReportUtils.buildOptimisticChatReport([accountID]);
}
// STEP 2: Get existing IOU/Expense report and update its total OR build a new optimistic one
// For Control policy expense chats, if the report is already approved, create a new expense report
- let oneOnOneIOUReport = oneOnOneChatReport.iouReportID ? lodashGet(allReports, `${ONYXKEYS.COLLECTION.REPORT}${oneOnOneChatReport.iouReportID}`, undefined) : undefined;
+ let oneOnOneIOUReport: OneOnOneIOUReport = oneOnOneChatReport.iouReportID ? allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${oneOnOneChatReport.iouReportID}`] : null;
const shouldCreateNewOneOnOneIOUReport =
- _.isUndefined(oneOnOneIOUReport) || (isOwnPolicyExpenseChat && ReportUtils.isControlPolicyExpenseReport(oneOnOneIOUReport) && ReportUtils.isReportApproved(oneOnOneIOUReport));
+ !oneOnOneIOUReport || (isOwnPolicyExpenseChat && ReportUtils.isControlPolicyExpenseReport(oneOnOneIOUReport) && ReportUtils.isReportApproved(oneOnOneIOUReport));
- if (shouldCreateNewOneOnOneIOUReport) {
+ if (!oneOnOneIOUReport || shouldCreateNewOneOnOneIOUReport) {
oneOnOneIOUReport = isOwnPolicyExpenseChat
- ? ReportUtils.buildOptimisticExpenseReport(oneOnOneChatReport.reportID, oneOnOneChatReport.policyID, currentUserAccountID, splitAmount, currency)
+ ? ReportUtils.buildOptimisticExpenseReport(oneOnOneChatReport.reportID, oneOnOneChatReport.policyID ?? '', currentUserAccountID, splitAmount, currency)
: ReportUtils.buildOptimisticIOUReport(currentUserAccountID, accountID, splitAmount, oneOnOneChatReport.reportID, currency);
} else if (isOwnPolicyExpenseChat) {
- // Because of the Expense reports are stored as negative values, we subtract the total from the amount
- oneOnOneIOUReport.total -= splitAmount;
+ if (typeof oneOnOneIOUReport?.total === 'number') {
+ // Because of the Expense reports are stored as negative values, we subtract the total from the amount
+ oneOnOneIOUReport.total -= splitAmount;
+ }
} else {
oneOnOneIOUReport = IOUUtils.updateIOUOwnerAndTotal(oneOnOneIOUReport, currentUserAccountID, splitAmount, currency);
}
@@ -1650,7 +1612,7 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco
comment,
[participant],
oneOnOneTransaction.transactionID,
- '',
+ undefined,
oneOnOneIOUReport.reportID,
undefined,
undefined,
@@ -1660,17 +1622,19 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco
);
// Add optimistic personal details for new participants
- const oneOnOnePersonalDetailListAction = shouldCreateOptimisticPersonalDetails
+ const oneOnOnePersonalDetailListAction: OnyxTypes.PersonalDetailsList = shouldCreateOptimisticPersonalDetails
? {
[accountID]: {
accountID,
avatar: UserUtils.getDefaultAvatarURL(accountID),
+ // Disabling this line since participant.displayName can be an empty string
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
displayName: LocalePhoneNumber.formatPhoneNumber(participant.displayName || email),
login: participant.login,
isOptimisticPersonalDetail: true,
},
}
- : undefined;
+ : {};
let oneOnOneReportPreviewAction = ReportActionsUtils.getReportPreviewAction(oneOnOneChatReport.reportID, oneOnOneIOUReport.reportID);
if (oneOnOneReportPreviewAction) {
@@ -1720,14 +1684,14 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco
failureData.push(...oneOnOneFailureData);
});
- const splitData = {
+ const splitData: SplitData = {
chatReportID: splitChatReport.reportID,
transactionID: splitTransaction.transactionID,
reportActionID: splitIOUReportAction.reportActionID,
policyID: splitChatReport.policyID,
};
- if (_.isEmpty(existingSplitChatReport)) {
+ if (!existingSplitChatReport) {
splitData.createdReportActionID = splitCreatedReportAction.reportActionID;
}
@@ -1739,19 +1703,22 @@ function createSplitsAndOnyxData(participants, currentUserLogin, currentUserAcco
}
/**
- * @param {Array} participants
- * @param {String} currentUserLogin
- * @param {Number} currentUserAccountID
- * @param {Number} amount - always in smallest currency unit
- * @param {String} comment
- * @param {String} currency
- * @param {String} merchant
- * @param {String} category
- * @param {String} tag
- * @param {String} existingSplitChatReportID - Either a group DM or a workspace chat
- * @param {Boolean} billable
- */
-function splitBill(participants, currentUserLogin, currentUserAccountID, amount, comment, currency, merchant, category, tag, existingSplitChatReportID = '', billable = false) {
+ * @param amount - always in smallest currency unit
+ * @param existingSplitChatReportID - Either a group DM or a workspace chat
+ */
+function splitBill(
+ participants: Participant[],
+ currentUserLogin: string,
+ currentUserAccountID: number,
+ amount: number,
+ comment: string,
+ currency: string,
+ merchant: string,
+ category: string,
+ tag: string,
+ existingSplitChatReportID = '',
+ billable = false,
+) {
const {splitData, splits, onyxData} = createSplitsAndOnyxData(
participants,
currentUserLogin,
@@ -1765,65 +1732,64 @@ function splitBill(participants, currentUserLogin, currentUserAccountID, amount,
existingSplitChatReportID,
billable,
);
- API.write(
- 'SplitBill',
- {
- reportID: splitData.chatReportID,
- amount,
- splits: JSON.stringify(splits),
- currency,
- comment,
- category,
- merchant,
- tag,
- billable,
- transactionID: splitData.transactionID,
- reportActionID: splitData.reportActionID,
- createdReportActionID: splitData.createdReportActionID,
- policyID: splitData.policyID,
- },
- onyxData,
- );
- resetMoneyRequestInfo();
+ const parameters: SplitBillParams = {
+ reportID: splitData.chatReportID,
+ amount,
+ splits: JSON.stringify(splits),
+ currency,
+ comment,
+ category,
+ merchant,
+ tag,
+ billable,
+ transactionID: splitData.transactionID,
+ reportActionID: splitData.reportActionID,
+ createdReportActionID: splitData.createdReportActionID,
+ policyID: splitData.policyID,
+ };
+
+ API.write(WRITE_COMMANDS.SPLIT_BILL, parameters, onyxData);
+
+ resetMoneyRequestInfo();
Navigation.dismissModal();
Report.notifyNewAction(splitData.chatReportID, currentUserAccountID);
}
/**
- * @param {Array} participants
- * @param {String} currentUserLogin
- * @param {Number} currentUserAccountID
- * @param {Number} amount - always in smallest currency unit
- * @param {String} comment
- * @param {String} currency
- * @param {String} merchant
- * @param {String} category
- * @param {String} tag
- * @param {Boolean} billable
- */
-function splitBillAndOpenReport(participants, currentUserLogin, currentUserAccountID, amount, comment, currency, merchant, category, tag, billable) {
- const {splitData, splits, onyxData} = createSplitsAndOnyxData(participants, currentUserLogin, currentUserAccountID, amount, comment, currency, merchant, category, tag, billable);
+ * @param amount - always in smallest currency unit
+ */
+function splitBillAndOpenReport(
+ participants: Participant[],
+ currentUserLogin: string,
+ currentUserAccountID: number,
+ amount: number,
+ comment: string,
+ currency: string,
+ merchant: string,
+ category: string,
+ tag: string,
+ billable: boolean,
+) {
+ const {splitData, splits, onyxData} = createSplitsAndOnyxData(participants, currentUserLogin, currentUserAccountID, amount, comment, currency, merchant, category, tag);
- API.write(
- 'SplitBillAndOpenReport',
- {
- reportID: splitData.chatReportID,
- amount,
- splits: JSON.stringify(splits),
- currency,
- merchant,
- comment,
- category,
- tag,
- billable,
- transactionID: splitData.transactionID,
- reportActionID: splitData.reportActionID,
- createdReportActionID: splitData.createdReportActionID,
- policyID: splitData.policyID,
- },
- onyxData,
- );
+ const parameters: SplitBillParams = {
+ reportID: splitData.chatReportID,
+ amount,
+ splits: JSON.stringify(splits),
+ currency,
+ merchant,
+ comment,
+ category,
+ tag,
+ billable,
+ transactionID: splitData.transactionID,
+ reportActionID: splitData.reportActionID,
+ createdReportActionID: splitData.createdReportActionID,
+ policyID: splitData.policyID,
+ };
+
+ API.write(WRITE_COMMANDS.SPLIT_BILL_AND_OPEN_REPORT, parameters, onyxData);
resetMoneyRequestInfo();
Navigation.dismissModal(splitData.chatReportID);
@@ -1833,28 +1799,30 @@ function splitBillAndOpenReport(participants, currentUserLogin, currentUserAccou
/** Used exclusively for starting a split bill request that contains a receipt, the split request will be completed once the receipt is scanned
* or user enters details manually.
*
- * @param {Array} participants
- * @param {String} currentUserLogin
- * @param {Number} currentUserAccountID
- * @param {String} comment
- * @param {String} category
- * @param {String} tag
- * @param {Object} receipt
- * @param {String} existingSplitChatReportID - Either a group DM or a workspace chat
- * @param {Boolean} billable
- */
-function startSplitBill(participants, currentUserLogin, currentUserAccountID, comment, category, tag, receipt, existingSplitChatReportID = '', billable = false) {
+ * @param existingSplitChatReportID - Either a group DM or a workspace chat
+ */
+function startSplitBill(
+ participants: Participant[],
+ currentUserLogin: string,
+ currentUserAccountID: number,
+ comment: string,
+ category: string,
+ tag: string,
+ receipt: Receipt,
+ existingSplitChatReportID = '',
+ billable = false,
+) {
const currentUserEmailForIOUSplit = OptionsListUtils.addSMSDomainIfPhoneNumber(currentUserLogin);
- const participantAccountIDs = _.map(participants, (participant) => Number(participant.accountID));
+ const participantAccountIDs = participants.map((participant) => Number(participant.accountID));
const existingSplitChatReport =
existingSplitChatReportID || participants[0].reportID
- ? allReports[`${ONYXKEYS.COLLECTION.REPORT}${existingSplitChatReportID || participants[0].reportID}`]
+ ? allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${existingSplitChatReportID || participants[0].reportID}`]
: ReportUtils.getChatByParticipants(participantAccountIDs);
- const splitChatReport = existingSplitChatReport || ReportUtils.buildOptimisticChatReport(participantAccountIDs);
- const isOwnPolicyExpenseChat = splitChatReport.isOwnPolicyExpenseChat || false;
+ const splitChatReport = existingSplitChatReport ?? ReportUtils.buildOptimisticChatReport(participantAccountIDs);
+ const isOwnPolicyExpenseChat = !!splitChatReport.isOwnPolicyExpenseChat;
const {name: filename, source, state = CONST.IOU.RECEIPT_STATE.SCANREADY} = receipt;
- const receiptObject = {state, source};
+ const receiptObject: Receipt = {state, source};
// ReportID is -2 (aka "deleted") on the group transaction
const splitTransaction = TransactionUtils.buildOptimisticTransaction(
@@ -1883,7 +1851,7 @@ function startSplitBill(participants, currentUserLogin, currentUserAccountID, co
comment,
participants,
splitTransaction.transactionID,
- '',
+ undefined,
'',
false,
false,
@@ -1892,8 +1860,8 @@ function startSplitBill(participants, currentUserLogin, currentUserAccountID, co
);
splitChatReport.lastReadTime = DateUtils.getDBTime();
- splitChatReport.lastMessageText = splitIOUReportAction.message[0].text;
- splitChatReport.lastMessageHtml = splitIOUReportAction.message[0].html;
+ splitChatReport.lastMessageText = splitIOUReportAction.message?.[0].text;
+ splitChatReport.lastMessageHtml = splitIOUReportAction.message?.[0].html;
// If we have an existing splitChatReport (group chat or workspace) use it's pending fields, otherwise indicate that we are adding a chat
if (!existingSplitChatReport) {
@@ -1902,7 +1870,7 @@ function startSplitBill(participants, currentUserLogin, currentUserAccountID, co
};
}
- const optimisticData = [
+ const optimisticData: OnyxUpdate[] = [
{
// Use set for new reports because it doesn't exist yet, is faster,
// and we need the data to be available when we navigate to the chat page
@@ -1910,14 +1878,22 @@ function startSplitBill(participants, currentUserLogin, currentUserAccountID, co
key: `${ONYXKEYS.COLLECTION.REPORT}${splitChatReport.reportID}`,
value: splitChatReport,
},
- {
- onyxMethod: existingSplitChatReport ? Onyx.METHOD.MERGE : Onyx.METHOD.SET,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${splitChatReport.reportID}`,
- value: {
- ...(existingSplitChatReport ? {} : {[splitChatCreatedReportAction.reportActionID]: splitChatCreatedReportAction}),
- [splitIOUReportAction.reportActionID]: splitIOUReportAction,
- },
- },
+ existingSplitChatReport
+ ? {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${splitChatReport.reportID}`,
+ value: {
+ [splitIOUReportAction.reportActionID]: splitIOUReportAction as OnyxTypes.ReportAction,
+ },
+ }
+ : {
+ onyxMethod: Onyx.METHOD.SET,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${splitChatReport.reportID}`,
+ value: {
+ [splitChatCreatedReportAction.reportActionID]: splitChatCreatedReportAction,
+ [splitIOUReportAction.reportActionID]: splitIOUReportAction as OnyxTypes.ReportAction,
+ },
+ },
{
onyxMethod: Onyx.METHOD.SET,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${splitTransaction.transactionID}`,
@@ -1925,7 +1901,7 @@ function startSplitBill(participants, currentUserLogin, currentUserAccountID, co
},
];
- const successData = [
+ const successData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${splitChatReport.reportID}`,
@@ -1949,7 +1925,7 @@ function startSplitBill(participants, currentUserLogin, currentUserAccountID, co
});
}
- const failureData = [
+ const failureData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${splitTransaction.transactionID}`,
@@ -1995,10 +1971,12 @@ function startSplitBill(participants, currentUserLogin, currentUserAccountID, co
);
}
- const splits = [{email: currentUserEmailForIOUSplit, accountID: currentUserAccountID}];
+ const splits: Split[] = [{email: currentUserEmailForIOUSplit, accountID: currentUserAccountID}];
- _.each(participants, (participant) => {
- const email = participant.isOwnPolicyExpenseChat ? '' : OptionsListUtils.addSMSDomainIfPhoneNumber(participant.login || participant.text).toLowerCase();
+ participants.forEach((participant) => {
+ // Disabling this line since participant.login can be an empty string
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
+ const email = participant.isOwnPolicyExpenseChat ? '' : OptionsListUtils.addSMSDomainIfPhoneNumber(participant.login || participant.text || '').toLowerCase();
const accountID = participant.isOwnPolicyExpenseChat ? 0 : Number(participant.accountID);
if (email === currentUserEmailForIOUSplit) {
return;
@@ -2013,7 +1991,7 @@ function startSplitBill(participants, currentUserLogin, currentUserAccountID, co
return;
}
- const participantPersonalDetails = allPersonalDetails[participant.accountID];
+ const participantPersonalDetails = allPersonalDetails[participant?.accountID ?? -1];
if (!participantPersonalDetails) {
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
@@ -2022,7 +2000,11 @@ function startSplitBill(participants, currentUserLogin, currentUserAccountID, co
[accountID]: {
accountID,
avatar: UserUtils.getDefaultAvatarURL(accountID),
+ // Disabling this line since participant.displayName can be an empty string
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
displayName: LocalePhoneNumber.formatPhoneNumber(participant.displayName || email),
+ // Disabling this line since participant.login can be an empty string
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
login: participant.login || participant.text,
isOptimisticPersonalDetail: true,
},
@@ -2036,7 +2018,7 @@ function startSplitBill(participants, currentUserLogin, currentUserAccountID, co
});
});
- _.each(participants, (participant) => {
+ participants.forEach((participant) => {
const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(participant);
if (!isPolicyExpenseChat) {
return;
@@ -2045,7 +2027,7 @@ function startSplitBill(participants, currentUserLogin, currentUserAccountID, co
const optimisticPolicyRecentlyUsedCategories = Policy.buildOptimisticPolicyRecentlyUsedCategories(participant.policyID, category);
const optimisticPolicyRecentlyUsedTags = Policy.buildOptimisticPolicyRecentlyUsedTags(participant.policyID, tag);
- if (!_.isEmpty(optimisticPolicyRecentlyUsedCategories)) {
+ if (optimisticPolicyRecentlyUsedCategories.length > 0) {
optimisticData.push({
onyxMethod: Onyx.METHOD.SET,
key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES}${participant.policyID}`,
@@ -2053,7 +2035,7 @@ function startSplitBill(participants, currentUserLogin, currentUserAccountID, co
});
}
- if (!_.isEmpty(optimisticPolicyRecentlyUsedTags)) {
+ if (!isEmptyObject(optimisticPolicyRecentlyUsedTags)) {
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${participant.policyID}`,
@@ -2073,44 +2055,42 @@ function startSplitBill(participants, currentUserLogin, currentUserAccountID, co
},
});
- API.write(
- 'StartSplitBill',
- {
- chatReportID: splitChatReport.reportID,
- reportActionID: splitIOUReportAction.reportActionID,
- transactionID: splitTransaction.transactionID,
- splits: JSON.stringify(splits),
- receipt,
- comment,
- category,
- tag,
- isFromGroupDM: !existingSplitChatReport,
- billable,
- ...(existingSplitChatReport ? {} : {createdReportActionID: splitChatCreatedReportAction.reportActionID}),
- },
- {optimisticData, successData, failureData},
- );
+ const parameters: StartSplitBillParams = {
+ chatReportID: splitChatReport.reportID,
+ reportActionID: splitIOUReportAction.reportActionID,
+ transactionID: splitTransaction.transactionID,
+ splits: JSON.stringify(splits),
+ receipt,
+ comment,
+ category,
+ tag,
+ isFromGroupDM: !existingSplitChatReport,
+ billable,
+ ...(existingSplitChatReport ? {} : {createdReportActionID: splitChatCreatedReportAction.reportActionID}),
+ };
+
+ API.write(WRITE_COMMANDS.START_SPLIT_BILL, parameters, {optimisticData, successData, failureData});
resetMoneyRequestInfo();
Navigation.dismissModalWithReport(splitChatReport);
- Report.notifyNewAction(splitChatReport.chatReportID, currentUserAccountID);
+ Report.notifyNewAction(splitChatReport.chatReportID ?? '', currentUserAccountID);
}
/** Used for editing a split bill while it's still scanning or when SmartScan fails, it completes a split bill started by startSplitBill above.
*
- * @param {number} chatReportID - The group chat or workspace reportID
- * @param {Object} reportAction - The split action that lives in the chatReport above
- * @param {Object} updatedTransaction - The updated **draft** split transaction
- * @param {Number} sessionAccountID - accountID of the current user
- * @param {String} sessionEmail - email of the current user
+ * @param chatReportID - The group chat or workspace reportID
+ * @param reportAction - The split action that lives in the chatReport above
+ * @param updatedTransaction - The updated **draft** split transaction
+ * @param sessionAccountID - accountID of the current user
+ * @param sessionEmail - email of the current user
*/
-function completeSplitBill(chatReportID, reportAction, updatedTransaction, sessionAccountID, sessionEmail) {
+function completeSplitBill(chatReportID: string, reportAction: OnyxTypes.ReportAction, updatedTransaction: OnyxTypes.Transaction, sessionAccountID: number, sessionEmail: string) {
const currentUserEmailForIOUSplit = OptionsListUtils.addSMSDomainIfPhoneNumber(sessionEmail);
const {transactionID} = updatedTransaction;
const unmodifiedTransaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`];
// Save optimistic updated transaction and action
- const optimisticData = [
+ const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
@@ -2133,7 +2113,7 @@ function completeSplitBill(chatReportID, reportAction, updatedTransaction, sessi
},
];
- const successData = [
+ const successData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
@@ -2142,11 +2122,11 @@ function completeSplitBill(chatReportID, reportAction, updatedTransaction, sessi
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`,
- value: null,
+ value: {pendingAction: null},
},
];
- const failureData = [
+ const failureData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
@@ -2167,25 +2147,25 @@ function completeSplitBill(chatReportID, reportAction, updatedTransaction, sessi
},
];
- const splitParticipants = updatedTransaction.comment.splits;
+ const splitParticipants: Split[] = updatedTransaction.comment.splits ?? [];
const {modifiedAmount: amount, modifiedCurrency: currency} = updatedTransaction;
// Exclude the current user when calculating the split amount, `calculateAmount` takes it into account
- const splitAmount = IOUUtils.calculateAmount(splitParticipants.length - 1, amount, currency, false);
+ const splitAmount = IOUUtils.calculateAmount(splitParticipants.length - 1, amount ?? 0, currency ?? '', false);
- const splits = [{email: currentUserEmailForIOUSplit}];
- _.each(splitParticipants, (participant) => {
+ const splits: Split[] = [{email: currentUserEmailForIOUSplit}];
+ splitParticipants.forEach((participant) => {
// Skip creating the transaction for the current user
if (participant.email === currentUserEmailForIOUSplit) {
return;
}
- const isPolicyExpenseChat = !_.isEmpty(participant.policyID);
+ const isPolicyExpenseChat = !!participant.policyID;
if (!isPolicyExpenseChat) {
// In case this is still the optimistic accountID saved in the splits array, return early as we cannot know
// if there is an existing chat between the split creator and this participant
// Instead, we will rely on Auth generating the report IDs and the user won't see any optimistic chats or reports created
- const participantPersonalDetails = allPersonalDetails[participant.accountID] || {};
+ const participantPersonalDetails: OnyxTypes.PersonalDetails | EmptyObject = allPersonalDetails[participant?.accountID ?? -1] ?? {};
if (!participantPersonalDetails || participantPersonalDetails.isOptimisticPersonalDetail) {
splits.push({
email: participant.email,
@@ -2194,36 +2174,38 @@ function completeSplitBill(chatReportID, reportAction, updatedTransaction, sessi
}
}
- let oneOnOneChatReport;
+ let oneOnOneChatReport: OnyxTypes.Report | null;
let isNewOneOnOneChatReport = false;
if (isPolicyExpenseChat) {
// The workspace chat reportID is saved in the splits array when starting a split bill with a workspace
- oneOnOneChatReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${participant.chatReportID}`];
+ oneOnOneChatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${participant.chatReportID}`] ?? null;
} else {
- const existingChatReport = ReportUtils.getChatByParticipants([participant.accountID]);
+ const existingChatReport = ReportUtils.getChatByParticipants(participant.accountID ? [participant.accountID] : []);
isNewOneOnOneChatReport = !existingChatReport;
- oneOnOneChatReport = existingChatReport || ReportUtils.buildOptimisticChatReport([participant.accountID]);
+ oneOnOneChatReport = existingChatReport ?? ReportUtils.buildOptimisticChatReport(participant.accountID ? [participant.accountID] : []);
}
- let oneOnOneIOUReport = oneOnOneChatReport.iouReportID ? lodashGet(allReports, `${ONYXKEYS.COLLECTION.REPORT}${oneOnOneChatReport.iouReportID}`, undefined) : undefined;
+ let oneOnOneIOUReport: OneOnOneIOUReport = oneOnOneChatReport?.iouReportID ? allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${oneOnOneChatReport.iouReportID}`] : null;
const shouldCreateNewOneOnOneIOUReport =
- _.isUndefined(oneOnOneIOUReport) || (isPolicyExpenseChat && ReportUtils.isControlPolicyExpenseReport(oneOnOneIOUReport) && ReportUtils.isReportApproved(oneOnOneIOUReport));
+ !oneOnOneIOUReport || (isPolicyExpenseChat && ReportUtils.isControlPolicyExpenseReport(oneOnOneIOUReport) && ReportUtils.isReportApproved(oneOnOneIOUReport));
- if (shouldCreateNewOneOnOneIOUReport) {
+ if (!oneOnOneIOUReport || shouldCreateNewOneOnOneIOUReport) {
oneOnOneIOUReport = isPolicyExpenseChat
- ? ReportUtils.buildOptimisticExpenseReport(oneOnOneChatReport.reportID, participant.policyID, sessionAccountID, splitAmount, currency)
- : ReportUtils.buildOptimisticIOUReport(sessionAccountID, participant.accountID, splitAmount, oneOnOneChatReport.reportID, currency);
+ ? ReportUtils.buildOptimisticExpenseReport(oneOnOneChatReport?.reportID ?? '', participant.policyID ?? '', sessionAccountID, splitAmount, currency ?? '')
+ : ReportUtils.buildOptimisticIOUReport(sessionAccountID, participant.accountID ?? -1, splitAmount, oneOnOneChatReport?.reportID ?? '', currency ?? '');
} else if (isPolicyExpenseChat) {
- // Because of the Expense reports are stored as negative values, we subtract the total from the amount
- oneOnOneIOUReport.total -= splitAmount;
+ if (typeof oneOnOneIOUReport?.total === 'number') {
+ // Because of the Expense reports are stored as negative values, we subtract the total from the amount
+ oneOnOneIOUReport.total -= splitAmount;
+ }
} else {
- oneOnOneIOUReport = IOUUtils.updateIOUOwnerAndTotal(oneOnOneIOUReport, sessionAccountID, splitAmount, currency);
+ oneOnOneIOUReport = IOUUtils.updateIOUOwnerAndTotal(oneOnOneIOUReport, sessionAccountID, splitAmount, currency ?? '');
}
const oneOnOneTransaction = TransactionUtils.buildOptimisticTransaction(
isPolicyExpenseChat ? -splitAmount : splitAmount,
- currency,
- oneOnOneIOUReport.reportID,
+ currency ?? '',
+ oneOnOneIOUReport?.reportID ?? '',
updatedTransaction.comment.comment,
updatedTransaction.modifiedCreated,
CONST.IOU.TYPE.SPLIT,
@@ -2238,15 +2220,15 @@ function completeSplitBill(chatReportID, reportAction, updatedTransaction, sessi
const oneOnOneIOUAction = ReportUtils.buildOptimisticIOUReportAction(
CONST.IOU.REPORT_ACTION_TYPE.CREATE,
splitAmount,
- currency,
- updatedTransaction.comment.comment,
+ currency ?? '',
+ updatedTransaction.comment.comment ?? '',
[participant],
oneOnOneTransaction.transactionID,
- '',
- oneOnOneIOUReport.reportID,
+ undefined,
+ oneOnOneIOUReport?.reportID,
);
- let oneOnOneReportPreviewAction = ReportActionsUtils.getReportPreviewAction(oneOnOneChatReport.reportID, oneOnOneIOUReport.reportID);
+ let oneOnOneReportPreviewAction = ReportActionsUtils.getReportPreviewAction(oneOnOneChatReport?.reportID ?? '', oneOnOneIOUReport?.reportID ?? '');
if (oneOnOneReportPreviewAction) {
oneOnOneReportPreviewAction = ReportUtils.updateReportPreview(oneOnOneIOUReport, oneOnOneReportPreviewAction);
} else {
@@ -2262,7 +2244,7 @@ function completeSplitBill(chatReportID, reportAction, updatedTransaction, sessi
oneOnOneIOUAction,
{},
oneOnOneReportPreviewAction,
- {},
+ [],
{},
isNewOneOnOneChatReport,
shouldCreateNewOneOnOneIOUReport,
@@ -2272,8 +2254,8 @@ function completeSplitBill(chatReportID, reportAction, updatedTransaction, sessi
email: participant.email,
accountID: participant.accountID,
policyID: participant.policyID,
- iouReportID: oneOnOneIOUReport.reportID,
- chatReportID: oneOnOneChatReport.reportID,
+ iouReportID: oneOnOneIOUReport?.reportID,
+ chatReportID: oneOnOneChatReport?.reportID,
transactionID: oneOnOneTransaction.transactionID,
reportActionID: oneOnOneIOUAction.reportActionID,
createdChatReportActionID: oneOnOneCreatedActionForChat.reportActionID,
@@ -2294,59 +2276,48 @@ function completeSplitBill(chatReportID, reportAction, updatedTransaction, sessi
comment: transactionComment,
category: transactionCategory,
tag: transactionTag,
- } = ReportUtils.getTransactionDetails(updatedTransaction);
+ } = ReportUtils.getTransactionDetails(updatedTransaction) ?? {};
- API.write(
- 'CompleteSplitBill',
- {
- transactionID,
- amount: transactionAmount,
- currency: transactionCurrency,
- created: transactionCreated,
- merchant: transactionMerchant,
- comment: transactionComment,
- category: transactionCategory,
- tag: transactionTag,
- splits: JSON.stringify(splits),
- },
- {optimisticData, successData, failureData},
- );
+ const parameters: CompleteSplitBillParams = {
+ transactionID,
+ amount: transactionAmount,
+ currency: transactionCurrency,
+ created: transactionCreated,
+ merchant: transactionMerchant,
+ comment: transactionComment,
+ category: transactionCategory,
+ tag: transactionTag,
+ splits: JSON.stringify(splits),
+ };
+
+ API.write(WRITE_COMMANDS.COMPLETE_SPLIT_BILL, parameters, {optimisticData, successData, failureData});
Navigation.dismissModal(chatReportID);
Report.notifyNewAction(chatReportID, sessionAccountID);
}
-/**
- * @param {String} transactionID
- * @param {Object} transactionChanges
- */
-function setDraftSplitTransaction(transactionID, transactionChanges = {}) {
+function setDraftSplitTransaction(transactionID: string, transactionChanges: TransactionChanges = {}) {
let draftSplitTransaction = allDraftSplitTransactions[`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`];
if (!draftSplitTransaction) {
draftSplitTransaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`];
}
- const updatedTransaction = TransactionUtils.getUpdatedTransaction(draftSplitTransaction, transactionChanges, false, false);
+ const updatedTransaction = draftSplitTransaction ? TransactionUtils.getUpdatedTransaction(draftSplitTransaction, transactionChanges, false, false) : null;
Onyx.merge(`${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`, updatedTransaction);
}
-/**
- * @param {String} transactionID
- * @param {Number} transactionThreadReportID
- * @param {Object} transactionChanges
- */
-function editRegularMoneyRequest(transactionID, transactionThreadReportID, transactionChanges) {
+function editRegularMoneyRequest(transactionID: string, transactionThreadReportID: string, transactionChanges: TransactionChanges) {
// STEP 1: Get all collections we're updating
- const transactionThread = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`];
+ const transactionThread = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`] ?? null;
const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`];
- const iouReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThread.parentReportID}`];
- const chatReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${iouReport.chatReportID}`];
+ const iouReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionThread?.parentReportID}`] ?? null;
+ const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${iouReport?.chatReportID}`] ?? null;
const isFromExpenseReport = ReportUtils.isExpenseReport(iouReport);
// STEP 2: Build new modified expense report action.
const updatedReportAction = ReportUtils.buildOptimisticModifiedExpenseReportAction(transactionThread, transaction, transactionChanges, isFromExpenseReport);
- const updatedTransaction = TransactionUtils.getUpdatedTransaction(transaction, transactionChanges, isFromExpenseReport);
+ const updatedTransaction = transaction ? TransactionUtils.getUpdatedTransaction(transaction, transactionChanges, isFromExpenseReport) : null;
// STEP 3: Compute the IOU total and update the report preview message so LHN amount owed is correct
// Should only update if the transaction matches the currency of the report, else we wait for the update
@@ -2354,20 +2325,22 @@ function editRegularMoneyRequest(transactionID, transactionThreadReportID, trans
let updatedMoneyRequestReport = {...iouReport};
const updatedChatReport = {...chatReport};
const diff = TransactionUtils.getAmount(transaction, true) - TransactionUtils.getAmount(updatedTransaction, true);
- if (updatedTransaction.currency === iouReport.currency && updatedTransaction.modifiedAmount && diff !== 0) {
- if (ReportUtils.isExpenseReport(iouReport)) {
+ if (updatedTransaction?.currency === iouReport?.currency && updatedTransaction?.modifiedAmount && diff !== 0) {
+ if (ReportUtils.isExpenseReport(iouReport) && typeof updatedMoneyRequestReport.total === 'number') {
updatedMoneyRequestReport.total += diff;
} else {
- updatedMoneyRequestReport = IOUUtils.updateIOUOwnerAndTotal(iouReport, updatedReportAction.actorAccountID, diff, TransactionUtils.getCurrency(transaction), false);
+ updatedMoneyRequestReport = iouReport
+ ? IOUUtils.updateIOUOwnerAndTotal(iouReport, updatedReportAction.actorAccountID ?? -1, diff, TransactionUtils.getCurrency(transaction), false)
+ : {};
}
updatedMoneyRequestReport.cachedTotal = CurrencyUtils.convertToDisplayString(updatedMoneyRequestReport.total, updatedTransaction.currency);
// Update the last message of the IOU report
const lastMessage = ReportUtils.getIOUReportActionMessage(
- iouReport.reportID,
+ iouReport?.reportID ?? '',
CONST.IOU.REPORT_ACTION_TYPE.CREATE,
- updatedMoneyRequestReport.total,
+ updatedMoneyRequestReport.total ?? 0,
'',
updatedTransaction.currency,
'',
@@ -2377,9 +2350,9 @@ function editRegularMoneyRequest(transactionID, transactionThreadReportID, trans
updatedMoneyRequestReport.lastMessageHtml = lastMessage[0].html;
// Update the last message of the chat report
- const hasNonReimbursableTransactions = ReportUtils.hasNonReimbursableTransactions(iouReport);
+ const hasNonReimbursableTransactions = ReportUtils.hasNonReimbursableTransactions(iouReport?.reportID);
const messageText = Localize.translateLocal(hasNonReimbursableTransactions ? 'iou.payerSpentAmount' : 'iou.payerOwesAmount', {
- payer: ReportUtils.getPersonalDetailsForAccountID(updatedMoneyRequestReport.managerID).login || '',
+ payer: ReportUtils.getPersonalDetailsForAccountID(updatedMoneyRequestReport.managerID ?? -1).login ?? '',
amount: CurrencyUtils.convertToDisplayString(updatedMoneyRequestReport.total, updatedMoneyRequestReport.currency),
});
updatedChatReport.lastMessageText = messageText;
@@ -2390,12 +2363,12 @@ function editRegularMoneyRequest(transactionID, transactionThreadReportID, trans
// STEP 4: Compose the optimistic data
const currentTime = DateUtils.getDBTime();
- const optimisticData = [
+ const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread.reportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread?.reportID}`,
value: {
- [updatedReportAction.reportActionID]: updatedReportAction,
+ [updatedReportAction.reportActionID]: updatedReportAction as OnyxTypes.ReportAction,
},
},
{
@@ -2405,12 +2378,12 @@ function editRegularMoneyRequest(transactionID, transactionThreadReportID, trans
},
{
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport?.reportID}`,
value: updatedMoneyRequestReport,
},
{
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.chatReportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport?.chatReportID}`,
value: updatedChatReport,
},
{
@@ -2421,58 +2394,59 @@ function editRegularMoneyRequest(transactionID, transactionThreadReportID, trans
lastVisibleActionCreated: currentTime,
},
},
- ...(!isScanning
- ? [
- {
- onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.reportID}`,
- value: {
- [transactionThread.parentReportActionID]: {
- whisperedToAccountIDs: [],
- },
- },
- },
- {
- onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.parentReportID}`,
- value: {
- [iouReport.parentReportActionID]: {
- whisperedToAccountIDs: [],
- },
- },
- },
- ]
- : []),
];
+ if (!isScanning) {
+ optimisticData.push(
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport?.reportID}`,
+ value: {
+ [transactionThread?.parentReportActionID ?? '']: {
+ whisperedToAccountIDs: [],
+ },
+ },
+ },
+ {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport?.parentReportID}`,
+ value: {
+ [iouReport?.parentReportActionID ?? '']: {
+ whisperedToAccountIDs: [],
+ },
+ },
+ },
+ );
+ }
+
// Update recently used categories if the category is changed
- if (_.has(transactionChanges, 'category')) {
- const optimisticPolicyRecentlyUsedCategories = Policy.buildOptimisticPolicyRecentlyUsedCategories(iouReport.policyID, transactionChanges.category);
- if (!_.isEmpty(optimisticPolicyRecentlyUsedCategories)) {
+ if ('category' in transactionChanges) {
+ const optimisticPolicyRecentlyUsedCategories = Policy.buildOptimisticPolicyRecentlyUsedCategories(iouReport?.policyID, transactionChanges.category);
+ if (optimisticPolicyRecentlyUsedCategories.length) {
optimisticData.push({
onyxMethod: Onyx.METHOD.SET,
- key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES}${iouReport.policyID}`,
+ key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES}${iouReport?.policyID}`,
value: optimisticPolicyRecentlyUsedCategories,
});
}
}
// Update recently used categories if the tag is changed
- if (_.has(transactionChanges, 'tag')) {
- const optimisticPolicyRecentlyUsedTags = Policy.buildOptimisticPolicyRecentlyUsedTags(iouReport.policyID, transactionChanges.tag);
- if (!_.isEmpty(optimisticPolicyRecentlyUsedTags)) {
+ if ('tag' in transactionChanges) {
+ const optimisticPolicyRecentlyUsedTags = Policy.buildOptimisticPolicyRecentlyUsedTags(iouReport?.policyID, transactionChanges.tag);
+ if (!isEmptyObject(optimisticPolicyRecentlyUsedTags)) {
optimisticData.push({
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${iouReport.policyID}`,
+ key: `${ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS}${iouReport?.policyID}`,
value: optimisticPolicyRecentlyUsedTags,
});
}
}
- const successData = [
+ const successData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread.reportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread?.reportID}`,
value: {
[updatedReportAction.reportActionID]: {pendingAction: null},
},
@@ -2495,15 +2469,15 @@ function editRegularMoneyRequest(transactionID, transactionThreadReportID, trans
},
{
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport?.reportID}`,
value: {pendingAction: null},
},
];
- const failureData = [
+ const failureData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread.reportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThread?.reportID}`,
value: {
[updatedReportAction.reportActionID]: {
errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericEditFailureMessage'),
@@ -2515,63 +2489,57 @@ function editRegularMoneyRequest(transactionID, transactionThreadReportID, trans
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
value: {
...transaction,
- modifiedCreated: transaction.modifiedCreated ? transaction.modifiedCreated : null,
- modifiedAmount: transaction.modifiedAmount ? transaction.modifiedAmount : null,
- modifiedCurrency: transaction.modifiedCurrency ? transaction.modifiedCurrency : null,
- modifiedMerchant: transaction.modifiedMerchant ? transaction.modifiedMerchant : null,
- modifiedWaypoints: transaction.modifiedWaypoints ? transaction.modifiedWaypoints : null,
+ modifiedCreated: transaction?.modifiedCreated ? transaction.modifiedCreated : null,
+ modifiedAmount: transaction?.modifiedAmount ? transaction.modifiedAmount : null,
+ modifiedCurrency: transaction?.modifiedCurrency ? transaction.modifiedCurrency : null,
+ modifiedMerchant: transaction?.modifiedMerchant ? transaction.modifiedMerchant : null,
+ modifiedWaypoints: transaction?.modifiedWaypoints ? transaction.modifiedWaypoints : null,
pendingFields: null,
},
},
{
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport?.reportID}`,
value: {
...iouReport,
- cachedTotal: iouReport.cachedTotal ? iouReport.cachedTotal : null,
+ cachedTotal: iouReport?.cachedTotal ? iouReport?.cachedTotal : null,
},
},
{
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.chatReportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport?.chatReportID}`,
value: chatReport,
},
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID}`,
value: {
- lastReadTime: transactionThread.lastReadTime,
- lastVisibleActionCreated: transactionThread.lastVisibleActionCreated,
+ lastReadTime: transactionThread?.lastReadTime,
+ lastVisibleActionCreated: transactionThread?.lastVisibleActionCreated,
},
},
];
// STEP 6: Call the API endpoint
- const {created, amount, currency, comment, merchant, category, billable, tag} = ReportUtils.getTransactionDetails(updatedTransaction);
- API.write(
- 'EditMoneyRequest',
- {
- transactionID,
- reportActionID: updatedReportAction.reportActionID,
- created,
- amount,
- currency,
- comment,
- merchant,
- category,
- billable,
- tag,
- },
- {optimisticData, successData, failureData},
- );
+ const {created, amount, currency, comment, merchant, category, billable, tag} = ReportUtils.getTransactionDetails(updatedTransaction) ?? {};
+
+ const parameters: EditMoneyRequestParams = {
+ transactionID,
+ reportActionID: updatedReportAction.reportActionID,
+ created,
+ amount,
+ currency,
+ comment,
+ merchant,
+ category,
+ billable,
+ tag,
+ };
+
+ API.write(WRITE_COMMANDS.EDIT_MONEY_REQUEST, parameters, {optimisticData, successData, failureData});
}
-/**
- * @param {object} transaction
- * @param {String} transactionThreadReportID
- * @param {Object} transactionChanges
- */
-function editMoneyRequest(transaction, transactionThreadReportID, transactionChanges) {
+function editMoneyRequest(transaction: OnyxTypes.Transaction, transactionThreadReportID: string, transactionChanges: TransactionChanges) {
if (TransactionUtils.isDistanceRequest(transaction)) {
updateDistanceRequest(transaction.transactionID, transactionThreadReportID, transactionChanges);
} else {
@@ -2579,46 +2547,35 @@ function editMoneyRequest(transaction, transactionThreadReportID, transactionCha
}
}
-/**
- * Updates the amount and currency fields of a money request
- *
- * @param {String} transactionID
- * @param {String} transactionThreadReportID
- * @param {String} currency
- * @param {Number} amount
- */
-function updateMoneyRequestAmountAndCurrency(transactionID, transactionThreadReportID, currency, amount) {
+/** Updates the amount and currency fields of a money request */
+function updateMoneyRequestAmountAndCurrency(transactionID: string, transactionThreadReportID: string, currency: string, amount: number) {
const transactionChanges = {
amount,
currency,
};
const {params, onyxData} = getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, transactionChanges, true);
- API.write('UpdateMoneyRequestAmountAndCurrency', params, onyxData);
+ API.write(WRITE_COMMANDS.UPDATE_MONEY_REQUEST_AMOUNT_AND_CURRENCY, params, onyxData);
}
-/**
- * @param {String | undefined} transactionID
- * @param {Object} reportAction - the money request reportAction we are deleting
- * @param {Boolean} isSingleTransactionView
- */
-function deleteMoneyRequest(transactionID, reportAction, isSingleTransactionView = false) {
+function deleteMoneyRequest(transactionID: string, reportAction: OnyxTypes.ReportAction, isSingleTransactionView = false) {
// STEP 1: Get all collections we're updating
- const iouReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${reportAction.originalMessage.IOUReportID}`];
- const chatReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${iouReport.chatReportID}`];
- const reportPreviewAction = ReportActionsUtils.getReportPreviewAction(iouReport.chatReportID, iouReport.reportID);
+ const iouReportID = reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.IOU ? reportAction.originalMessage.IOUReportID : '';
+ const iouReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${iouReportID}`] ?? null;
+ const chatReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${iouReport?.chatReportID}`];
+ const reportPreviewAction = ReportActionsUtils.getReportPreviewAction(iouReport?.chatReportID ?? '', iouReport?.reportID ?? '');
const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`];
const transactionViolations = allTransactionViolations[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`];
const transactionThreadID = reportAction.childReportID;
let transactionThread = null;
if (transactionThreadID) {
- transactionThread = allReports[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadID}`];
+ transactionThread = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadID}`] ?? null;
}
// STEP 2: Decide if we need to:
// 1. Delete the transactionThread - delete if there are no visible comments in the thread
// 2. Update the moneyRequestPreview to show [Deleted request] - update if the transactionThread exists AND it isn't being deleted
- const shouldDeleteTransactionThread = transactionThreadID ? lodashGet(reportAction, 'childVisibleActionCount', 0) === 0 : false;
- const shouldShowDeletedRequestMessage = transactionThreadID && !shouldDeleteTransactionThread;
+ const shouldDeleteTransactionThread = transactionThreadID ? (reportAction?.childVisibleActionCount ?? 0) === 0 : false;
+ const shouldShowDeletedRequestMessage = !!transactionThreadID && !shouldDeleteTransactionThread;
// STEP 3: Update the IOU reportAction and decide if the iouReport should be deleted. We delete the iouReport if there are no visible comments left in the report.
const updatedReportAction = {
@@ -2637,127 +2594,135 @@ function deleteMoneyRequest(transactionID, reportAction, isSingleTransactionView
originalMessage: {
IOUTransactionID: null,
},
- errors: null,
+ errors: undefined,
},
- };
+ } as OnyxTypes.ReportActions;
- const lastVisibleAction = ReportActionsUtils.getLastVisibleAction(iouReport.reportID, updatedReportAction);
- const iouReportLastMessageText = ReportActionsUtils.getLastVisibleMessage(iouReport.reportID, updatedReportAction).lastMessageText;
+ const lastVisibleAction = ReportActionsUtils.getLastVisibleAction(iouReport?.reportID ?? '', updatedReportAction);
+ const iouReportLastMessageText = ReportActionsUtils.getLastVisibleMessage(iouReport?.reportID ?? '', updatedReportAction).lastMessageText;
const shouldDeleteIOUReport =
iouReportLastMessageText.length === 0 && !ReportActionsUtils.isDeletedParentAction(lastVisibleAction) && (!transactionThreadID || shouldDeleteTransactionThread);
// STEP 4: Update the iouReport and reportPreview with new totals and messages if it wasn't deleted
- let updatedIOUReport = {...iouReport};
- const updatedReportPreviewAction = {...reportPreviewAction};
+ let updatedIOUReport: OnyxTypes.Report | null;
+ const updatedReportPreviewAction: OnyxTypes.ReportAction | EmptyObject = {...reportPreviewAction};
updatedReportPreviewAction.pendingAction = shouldDeleteIOUReport ? CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE : CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE;
- if (ReportUtils.isExpenseReport(iouReport)) {
+ if (iouReport && ReportUtils.isExpenseReport(iouReport)) {
updatedIOUReport = {...iouReport};
- // Because of the Expense reports are stored as negative values, we add the total from the amount
- updatedIOUReport.total += TransactionUtils.getAmount(transaction, true);
+ if (typeof updatedIOUReport.total === 'number') {
+ // Because of the Expense reports are stored as negative values, we add the total from the amount
+ updatedIOUReport.total += TransactionUtils.getAmount(transaction, true);
+ }
} else {
updatedIOUReport = IOUUtils.updateIOUOwnerAndTotal(
iouReport,
- reportAction.actorAccountID,
+ reportAction.actorAccountID ?? -1,
TransactionUtils.getAmount(transaction, false),
TransactionUtils.getCurrency(transaction),
true,
);
}
- updatedIOUReport.lastMessageText = iouReportLastMessageText;
- updatedIOUReport.lastVisibleActionCreated = lodashGet(lastVisibleAction, 'created');
+ if (updatedIOUReport) {
+ updatedIOUReport.lastMessageText = iouReportLastMessageText;
+ updatedIOUReport.lastVisibleActionCreated = lastVisibleAction?.created;
+ }
- const hasNonReimbursableTransactions = ReportUtils.hasNonReimbursableTransactions(iouReport);
+ const hasNonReimbursableTransactions = ReportUtils.hasNonReimbursableTransactions(iouReport?.reportID);
const messageText = Localize.translateLocal(hasNonReimbursableTransactions ? 'iou.payerSpentAmount' : 'iou.payerOwesAmount', {
- payer: ReportUtils.getPersonalDetailsForAccountID(updatedIOUReport.managerID).login || '',
- amount: CurrencyUtils.convertToDisplayString(updatedIOUReport.total, updatedIOUReport.currency),
+ payer: ReportUtils.getPersonalDetailsForAccountID(updatedIOUReport?.managerID ?? -1).login ?? '',
+ amount: CurrencyUtils.convertToDisplayString(updatedIOUReport?.total, updatedIOUReport?.currency),
});
- updatedReportPreviewAction.message[0].text = messageText;
- updatedReportPreviewAction.message[0].html = shouldDeleteIOUReport ? '' : messageText;
- if (reportPreviewAction.childMoneyRequestCount > 0) {
+ if (updatedReportPreviewAction?.message?.[0]) {
+ updatedReportPreviewAction.message[0].text = messageText;
+ updatedReportPreviewAction.message[0].html = shouldDeleteIOUReport ? '' : messageText;
+ }
+
+ if (updatedReportPreviewAction && reportPreviewAction?.childMoneyRequestCount && reportPreviewAction?.childMoneyRequestCount > 0) {
updatedReportPreviewAction.childMoneyRequestCount = reportPreviewAction.childMoneyRequestCount - 1;
}
// STEP 5: Build Onyx data
- const optimisticData = [
+ const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.SET,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
value: null,
},
- ...(Permissions.canUseViolations(betas)
- ? [
- {
- onyxMethod: Onyx.METHOD.SET,
- key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`,
- value: null,
- },
- ]
- : []),
- ...(shouldDeleteTransactionThread
- ? [
- {
- onyxMethod: Onyx.METHOD.SET,
- key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadID}`,
- value: null,
- },
- {
- onyxMethod: Onyx.METHOD.SET,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadID}`,
- value: null,
- },
- ]
- : []),
+ ];
+
+ if (Permissions.canUseViolations(betas)) {
+ optimisticData.push({
+ onyxMethod: Onyx.METHOD.SET,
+ key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`,
+ value: null,
+ });
+ }
+
+ if (shouldDeleteTransactionThread) {
+ optimisticData.push(
+ {
+ onyxMethod: Onyx.METHOD.SET,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadID}`,
+ value: null,
+ },
+ {
+ onyxMethod: Onyx.METHOD.SET,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadID}`,
+ value: null,
+ },
+ );
+ }
+
+ optimisticData.push(
{
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.reportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport?.reportID}`,
value: updatedReportAction,
},
{
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport?.reportID}`,
value: updatedIOUReport,
},
{
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport.reportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport?.reportID}`,
value: {
- [reportPreviewAction.reportActionID]: updatedReportPreviewAction,
+ [reportPreviewAction?.reportActionID ?? '']: updatedReportPreviewAction,
},
},
- ...(!shouldDeleteIOUReport && updatedReportPreviewAction.childMoneyRequestCount === 0
- ? [
- {
- onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`,
- value: {
- hasOutstandingChildRequest: false,
- },
- },
- ]
- : []),
- ...(shouldDeleteIOUReport
- ? [
- {
- onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`,
- value: {
- hasOutstandingChildRequest: false,
- iouReportID: null,
- lastMessageText: ReportActionsUtils.getLastVisibleMessage(iouReport.chatReportID, {[reportPreviewAction.reportActionID]: null}).lastMessageText,
- lastVisibleActionCreated: lodashGet(ReportActionsUtils.getLastVisibleAction(iouReport.chatReportID, {[reportPreviewAction.reportActionID]: null}), 'created'),
- },
- },
- ]
- : []),
- ];
+ );
- const successData = [
+ if (!shouldDeleteIOUReport && updatedReportPreviewAction.childMoneyRequestCount === 0) {
+ optimisticData.push({
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport?.reportID}`,
+ value: {
+ hasOutstandingChildRequest: false,
+ },
+ });
+ }
+
+ if (shouldDeleteIOUReport) {
+ optimisticData.push({
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport?.reportID}`,
+ value: {
+ hasOutstandingChildRequest: false,
+ iouReportID: null,
+ lastMessageText: ReportActionsUtils.getLastVisibleMessage(iouReport?.chatReportID ?? '', {[reportPreviewAction?.reportActionID ?? '']: null})?.lastMessageText,
+ lastVisibleActionCreated: ReportActionsUtils.getLastVisibleAction(iouReport?.chatReportID ?? '', {[reportPreviewAction?.reportActionID ?? '']: null})?.created,
+ },
+ });
+ }
+
+ const successData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.reportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport?.reportID}`,
value: {
[reportAction.reportActionID]: shouldDeleteIOUReport
? null
@@ -2768,9 +2733,9 @@ function deleteMoneyRequest(transactionID, reportAction, isSingleTransactionView
},
{
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport.reportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport?.reportID}`,
value: {
- [reportPreviewAction.reportActionID]: shouldDeleteIOUReport
+ [reportPreviewAction?.reportActionID ?? '']: shouldDeleteIOUReport
? null
: {
pendingAction: null,
@@ -2778,44 +2743,44 @@ function deleteMoneyRequest(transactionID, reportAction, isSingleTransactionView
},
},
},
- ...(shouldDeleteIOUReport
- ? [
- {
- onyxMethod: Onyx.METHOD.SET,
- key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`,
- value: null,
- },
- ]
- : []),
];
- const failureData = [
+ if (shouldDeleteIOUReport) {
+ successData.push({
+ onyxMethod: Onyx.METHOD.SET,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport?.reportID}`,
+ value: null,
+ });
+ }
+
+ const failureData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.SET,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
value: transaction,
},
- ...(Permissions.canUseViolations(betas)
- ? [
- {
- onyxMethod: Onyx.METHOD.SET,
- key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`,
- value: transactionViolations,
- },
- ]
- : []),
- ...(shouldDeleteTransactionThread
- ? [
- {
- onyxMethod: Onyx.METHOD.SET,
- key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadID}`,
- value: transactionThread,
- },
- ]
- : []),
+ ];
+
+ if (Permissions.canUseViolations(betas)) {
+ failureData.push({
+ onyxMethod: Onyx.METHOD.SET,
+ key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`,
+ value: transactionViolations,
+ });
+ }
+
+ if (shouldDeleteTransactionThread) {
+ failureData.push({
+ onyxMethod: Onyx.METHOD.SET,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadID}`,
+ value: transactionThread,
+ });
+ }
+
+ failureData.push(
{
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.reportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport?.reportID}`,
value: {
[reportAction.reportActionID]: {
...reportAction,
@@ -2824,78 +2789,82 @@ function deleteMoneyRequest(transactionID, reportAction, isSingleTransactionView
},
},
},
- {
- onyxMethod: shouldDeleteIOUReport ? Onyx.METHOD.SET : Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`,
- value: iouReport,
- },
+ shouldDeleteIOUReport
+ ? {
+ onyxMethod: Onyx.METHOD.SET,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport?.reportID}`,
+ value: iouReport,
+ }
+ : {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport?.reportID}`,
+ value: iouReport,
+ },
{
onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport.reportID}`,
+ key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport?.reportID}`,
value: {
- [reportPreviewAction.reportActionID]: {
+ [reportPreviewAction?.reportActionID ?? '']: {
...reportPreviewAction,
errors: ErrorUtils.getMicroSecondOnyxError('iou.error.genericDeleteFailureMessage'),
},
},
},
- ...(shouldDeleteIOUReport
- ? [
- {
- onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`,
- value: chatReport,
- },
- ]
- : []),
- ...(!shouldDeleteIOUReport && updatedReportPreviewAction.childMoneyRequestCount === 0
- ? [
- {
- onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`,
- value: {
- hasOutstandingChildRequest: true,
- },
- },
- ]
- : []),
- ];
+ );
+
+ if (chatReport && shouldDeleteIOUReport) {
+ failureData.push({
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`,
+ value: chatReport,
+ });
+ }
+
+ if (!shouldDeleteIOUReport && updatedReportPreviewAction.childMoneyRequestCount === 0) {
+ failureData.push({
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport?.reportID}`,
+ value: {
+ hasOutstandingChildRequest: true,
+ },
+ });
+ }
+
+ const parameters: DeleteMoneyRequestParams = {
+ transactionID,
+ reportActionID: reportAction.reportActionID,
+ };
// STEP 6: Make the API request
- API.write(
- 'DeleteMoneyRequest',
- {
- transactionID,
- reportActionID: reportAction.reportActionID,
- },
- {optimisticData, successData, failureData},
- );
+ API.write(WRITE_COMMANDS.DELETE_MONEY_REQUEST, parameters, {optimisticData, successData, failureData});
// STEP 7: Navigate the user depending on which page they are on and which resources were deleted
- if (isSingleTransactionView && shouldDeleteTransactionThread && !shouldDeleteIOUReport) {
+ if (iouReport && isSingleTransactionView && shouldDeleteTransactionThread && !shouldDeleteIOUReport) {
// Pop the deleted report screen before navigating. This prevents navigating to the Concierge chat due to the missing report.
Navigation.goBack(ROUTES.REPORT_WITH_ID.getRoute(iouReport.reportID));
return;
}
- if (shouldDeleteIOUReport) {
+ if (iouReport?.chatReportID && shouldDeleteIOUReport) {
// Pop the deleted report screen before navigating. This prevents navigating to the Concierge chat due to the missing report.
Navigation.goBack(ROUTES.REPORT_WITH_ID.getRoute(iouReport.chatReportID));
}
}
/**
- * @param {Object} report
- * @param {Number} amount
- * @param {String} currency
- * @param {String} comment
- * @param {String} paymentMethodType
- * @param {String} managerID - Account ID of the person sending the money
- * @param {Object} recipient - The user receiving the money
- * @returns {Object}
- */
-function getSendMoneyParams(report, amount, currency, comment, paymentMethodType, managerID, recipient) {
- const recipientEmail = OptionsListUtils.addSMSDomainIfPhoneNumber(recipient.login);
+ * @param managerID - Account ID of the person sending the money
+ * @param recipient - The user receiving the money
+ */
+function getSendMoneyParams(
+ report: OnyxTypes.Report,
+ amount: number,
+ currency: string,
+ comment: string,
+ paymentMethodType: PaymentMethodType,
+ managerID: number,
+ recipient: Participant,
+): SendMoneyParamsData {
+ const recipientEmail = OptionsListUtils.addSMSDomainIfPhoneNumber(recipient.login ?? '');
const recipientAccountID = Number(recipient.accountID);
const newIOUReportDetails = JSON.stringify({
amount,
@@ -2918,7 +2887,7 @@ function getSendMoneyParams(report, amount, currency, comment, paymentMethodType
const optimisticIOUReport = ReportUtils.buildOptimisticIOUReport(recipientAccountID, managerID, amount, chatReport.reportID, currency, true);
const optimisticTransaction = TransactionUtils.buildOptimisticTransaction(amount, currency, optimisticIOUReport.reportID, comment);
- const optimisticTransactionData = {
+ const optimisticTransactionData: OnyxUpdate = {
onyxMethod: Onyx.METHOD.SET,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${optimisticTransaction.transactionID}`,
value: optimisticTransaction,
@@ -2941,36 +2910,49 @@ function getSendMoneyParams(report, amount, currency, comment, paymentMethodType
const reportPreviewAction = ReportUtils.buildOptimisticReportPreview(chatReport, optimisticIOUReport);
- // First, add data that will be used in all cases
- const optimisticChatReportData = {
- onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`,
- value: {
- ...chatReport,
- lastReadTime: DateUtils.getDBTime(),
- lastVisibleActionCreated: reportPreviewAction.created,
- },
- };
- const optimisticIOUReportData = {
+ // Change the method to set for new reports because it doesn't exist yet, is faster,
+ // and we need the data to be available when we navigate to the chat page
+ const optimisticChatReportData: OnyxUpdate = isNewChat
+ ? {
+ onyxMethod: Onyx.METHOD.SET,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`,
+ value: {
+ ...chatReport,
+ // Set and clear pending fields on the chat report
+ pendingFields: {createChat: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD},
+ lastReadTime: DateUtils.getDBTime(),
+ lastVisibleActionCreated: reportPreviewAction.created,
+ },
+ }
+ : {
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`,
+ value: {
+ ...chatReport,
+ lastReadTime: DateUtils.getDBTime(),
+ lastVisibleActionCreated: reportPreviewAction.created,
+ },
+ };
+ const optimisticIOUReportData: OnyxUpdate = {
onyxMethod: Onyx.METHOD.SET,
key: `${ONYXKEYS.COLLECTION.REPORT}${optimisticIOUReport.reportID}`,
value: {
...optimisticIOUReport,
- lastMessageText: optimisticIOUReportAction.message[0].text,
- lastMessageHtml: optimisticIOUReportAction.message[0].html,
+ lastMessageText: optimisticIOUReportAction.message?.[0].text,
+ lastMessageHtml: optimisticIOUReportAction.message?.[0].html,
},
};
- const optimisticIOUReportActionsData = {
+ const optimisticIOUReportActionsData: OnyxUpdate = {
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${optimisticIOUReport.reportID}`,
value: {
[optimisticIOUReportAction.reportActionID]: {
- ...optimisticIOUReportAction,
+ ...(optimisticIOUReportAction as OnyxTypes.ReportAction),
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
},
},
};
- const optimisticChatReportActionsData = {
+ const optimisticChatReportActionsData: OnyxUpdate = {
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReport.reportID}`,
value: {
@@ -2978,7 +2960,7 @@ function getSendMoneyParams(report, amount, currency, comment, paymentMethodType
},
};
- const successData = [
+ const successData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${optimisticIOUReport.reportID}`,
@@ -3004,7 +2986,7 @@ function getSendMoneyParams(report, amount, currency, comment, paymentMethodType
},
];
- const failureData = [
+ const failureData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${optimisticTransaction.transactionID}`,
@@ -3014,26 +2996,19 @@ function getSendMoneyParams(report, amount, currency, comment, paymentMethodType
},
];
- let optimisticPersonalDetailListData = {};
+ let optimisticPersonalDetailListData: OnyxUpdate | EmptyObject = {};
// Now, let's add the data we need just when we are creating a new chat report
if (isNewChat) {
- // Change the method to set for new reports because it doesn't exist yet, is faster,
- // and we need the data to be available when we navigate to the chat page
- optimisticChatReportData.onyxMethod = Onyx.METHOD.SET;
- optimisticIOUReportData.onyxMethod = Onyx.METHOD.SET;
-
- // Set and clear pending fields on the chat report
- optimisticChatReportData.value.pendingFields = {createChat: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD};
successData.push({
onyxMethod: Onyx.METHOD.MERGE,
- key: optimisticChatReportData.key,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`,
value: {pendingFields: null},
});
failureData.push(
{
onyxMethod: Onyx.METHOD.MERGE,
- key: optimisticChatReportData.key,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`,
value: {
errorFields: {
createChat: ErrorUtils.getMicroSecondOnyxError('report.genericCreateReportFailureMessage'),
@@ -3059,14 +3034,18 @@ function getSendMoneyParams(report, amount, currency, comment, paymentMethodType
[recipientAccountID]: {
accountID: recipientAccountID,
avatar: UserUtils.getDefaultAvatarURL(recipient.accountID),
+ // Disabling this line since participant.displayName can be an empty string
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
displayName: recipient.displayName || recipient.login,
login: recipient.login,
},
},
};
- // Add an optimistic created action to the optimistic chat reportActions data
- optimisticChatReportActionsData.value[optimisticCreatedAction.reportActionID] = optimisticCreatedAction;
+ if (optimisticChatReportActionsData.value) {
+ // Add an optimistic created action to the optimistic chat reportActions data
+ optimisticChatReportActionsData.value[optimisticCreatedAction.reportActionID] = optimisticCreatedAction;
+ }
} else {
failureData.push({
onyxMethod: Onyx.METHOD.MERGE,
@@ -3079,8 +3058,8 @@ function getSendMoneyParams(report, amount, currency, comment, paymentMethodType
});
}
- const optimisticData = [optimisticChatReportData, optimisticIOUReportData, optimisticChatReportActionsData, optimisticIOUReportActionsData, optimisticTransactionData];
- if (!_.isEmpty(optimisticPersonalDetailListData)) {
+ const optimisticData: OnyxUpdate[] = [optimisticChatReportData, optimisticIOUReportData, optimisticChatReportActionsData, optimisticIOUReportActionsData, optimisticTransactionData];
+ if (!isEmptyObject(optimisticPersonalDetailListData)) {
optimisticData.push(optimisticPersonalDetailListData);
}
@@ -3092,7 +3071,7 @@ function getSendMoneyParams(report, amount, currency, comment, paymentMethodType
paymentMethodType,
transactionID: optimisticTransaction.transactionID,
newIOUReportDetails,
- createdReportActionID: isNewChat ? optimisticCreatedAction.reportActionID : 0,
+ createdReportActionID: isNewChat ? optimisticCreatedAction.reportActionID : '',
reportPreviewReportActionID: reportPreviewAction.reportActionID,
},
optimisticData,
@@ -3101,18 +3080,11 @@ function getSendMoneyParams(report, amount, currency, comment, paymentMethodType
};
}
-/**
- * @param {Object} chatReport
- * @param {Object} iouReport
- * @param {Object} recipient
- * @param {String} paymentMethodType
- * @returns {Object}
- */
-function getPayMoneyRequestParams(chatReport, iouReport, recipient, paymentMethodType) {
+function getPayMoneyRequestParams(chatReport: OnyxTypes.Report, iouReport: OnyxTypes.Report, recipient: Participant, paymentMethodType: PaymentMethodType): PayMoneyRequestData {
const optimisticIOUReportAction = ReportUtils.buildOptimisticIOUReportAction(
CONST.IOU.REPORT_ACTION_TYPE.PAY,
- -iouReport.total,
- iouReport.currency,
+ -(iouReport.total ?? 0),
+ iouReport.currency ?? '',
'',
[recipient],
'',
@@ -3129,9 +3101,9 @@ function getPayMoneyRequestParams(chatReport, iouReport, recipient, paymentMetho
optimisticReportPreviewAction = ReportUtils.updateReportPreview(iouReport, reportPreviewAction, true);
}
- const currentNextStep = lodashGet(allNextSteps, `${ONYXKEYS.COLLECTION.NEXT_STEP}${iouReport.reportID}`, null);
+ const currentNextStep = allNextSteps[`${ONYXKEYS.COLLECTION.NEXT_STEP}${iouReport.reportID}`] ?? null;
- const optimisticData = [
+ const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`,
@@ -3141,8 +3113,8 @@ function getPayMoneyRequestParams(chatReport, iouReport, recipient, paymentMetho
lastVisibleActionCreated: optimisticIOUReportAction.created,
hasOutstandingChildRequest: false,
iouReportID: null,
- lastMessageText: optimisticIOUReportAction.message[0].text,
- lastMessageHtml: optimisticIOUReportAction.message[0].html,
+ lastMessageText: optimisticIOUReportAction.message?.[0].text,
+ lastMessageHtml: optimisticIOUReportAction.message?.[0].html,
},
},
{
@@ -3150,7 +3122,7 @@ function getPayMoneyRequestParams(chatReport, iouReport, recipient, paymentMetho
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.reportID}`,
value: {
[optimisticIOUReportAction.reportActionID]: {
- ...optimisticIOUReportAction,
+ ...(optimisticIOUReportAction as OnyxTypes.ReportAction),
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
},
},
@@ -3160,8 +3132,8 @@ function getPayMoneyRequestParams(chatReport, iouReport, recipient, paymentMetho
key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`,
value: {
...iouReport,
- lastMessageText: optimisticIOUReportAction.message[0].text,
- lastMessageHtml: optimisticIOUReportAction.message[0].html,
+ lastMessageText: optimisticIOUReportAction.message?.[0].text,
+ lastMessageHtml: optimisticIOUReportAction.message?.[0].html,
hasOutstandingChildRequest: false,
statusNum: CONST.REPORT.STATUS_NUM.REIMBURSED,
},
@@ -3169,11 +3141,11 @@ function getPayMoneyRequestParams(chatReport, iouReport, recipient, paymentMetho
{
onyxMethod: Onyx.METHOD.MERGE,
key: ONYXKEYS.NVP_LAST_PAYMENT_METHOD,
- value: {[iouReport.policyID]: paymentMethodType},
+ value: {[iouReport.policyID ?? '']: paymentMethodType},
},
];
- const successData = [
+ const successData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.reportID}`,
@@ -3185,7 +3157,7 @@ function getPayMoneyRequestParams(chatReport, iouReport, recipient, paymentMetho
},
];
- const failureData = [
+ const failureData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${iouReport.reportID}`,
@@ -3207,7 +3179,7 @@ function getPayMoneyRequestParams(chatReport, iouReport, recipient, paymentMetho
},
];
- if (!_.isNull(currentNextStep)) {
+ if (currentNextStep) {
optimisticData.push({
onyxMethod: Onyx.METHOD.SET,
key: `${ONYXKEYS.COLLECTION.NEXT_STEP}${iouReport.reportID}`,
@@ -3254,17 +3226,13 @@ function getPayMoneyRequestParams(chatReport, iouReport, recipient, paymentMetho
}
/**
- * @param {Object} report
- * @param {Number} amount
- * @param {String} currency
- * @param {String} comment
- * @param {String} managerID - Account ID of the person sending the money
- * @param {Object} recipient - The user receiving the money
+ * @param managerID - Account ID of the person sending the money
+ * @param recipient - The user receiving the money
*/
-function sendMoneyElsewhere(report, amount, currency, comment, managerID, recipient) {
+function sendMoneyElsewhere(report: OnyxTypes.Report, amount: number, currency: string, comment: string, managerID: number, recipient: Participant) {
const {params, optimisticData, successData, failureData} = getSendMoneyParams(report, amount, currency, comment, CONST.IOU.PAYMENT_TYPE.ELSEWHERE, managerID, recipient);
- API.write('SendMoneyElsewhere', params, {optimisticData, successData, failureData});
+ API.write(WRITE_COMMANDS.SEND_MONEY_ELSEWHERE, params, {optimisticData, successData, failureData});
resetMoneyRequestInfo();
Navigation.dismissModal(params.chatReportID);
@@ -3272,52 +3240,48 @@ function sendMoneyElsewhere(report, amount, currency, comment, managerID, recipi
}
/**
- * @param {Object} report
- * @param {Number} amount
- * @param {String} currency
- * @param {String} comment
- * @param {String} managerID - Account ID of the person sending the money
- * @param {Object} recipient - The user receiving the money
+ * @param managerID - Account ID of the person sending the money
+ * @param recipient - The user receiving the money
*/
-function sendMoneyWithWallet(report, amount, currency, comment, managerID, recipient) {
+function sendMoneyWithWallet(report: OnyxTypes.Report, amount: number, currency: string, comment: string, managerID: number, recipient: Participant) {
const {params, optimisticData, successData, failureData} = getSendMoneyParams(report, amount, currency, comment, CONST.IOU.PAYMENT_TYPE.EXPENSIFY, managerID, recipient);
- API.write('SendMoneyWithWallet', params, {optimisticData, successData, failureData});
+ API.write(WRITE_COMMANDS.SEND_MONEY_WITH_WALLET, params, {optimisticData, successData, failureData});
resetMoneyRequestInfo();
Navigation.dismissModal(params.chatReportID);
Report.notifyNewAction(params.chatReportID, managerID);
}
-function approveMoneyRequest(expenseReport) {
- const currentNextStep = lodashGet(allNextSteps, `${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport.reportID}`, null);
+function approveMoneyRequest(expenseReport: OnyxTypes.Report | EmptyObject) {
+ const currentNextStep = allNextSteps[`${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport.reportID}`] ?? null;
- const optimisticApprovedReportAction = ReportUtils.buildOptimisticApprovedReportAction(expenseReport.total, expenseReport.currency, expenseReport.reportID);
+ const optimisticApprovedReportAction = ReportUtils.buildOptimisticApprovedReportAction(expenseReport.total ?? 0, expenseReport.currency ?? '', expenseReport.reportID);
- const optimisticReportActionsData = {
+ const optimisticReportActionsData: OnyxUpdate = {
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`,
value: {
[optimisticApprovedReportAction.reportActionID]: {
- ...optimisticApprovedReportAction,
+ ...(optimisticApprovedReportAction as OnyxTypes.ReportAction),
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
},
},
};
- const optimisticIOUReportData = {
+ const optimisticIOUReportData: OnyxUpdate = {
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT}${expenseReport.reportID}`,
value: {
...expenseReport,
- lastMessageText: optimisticApprovedReportAction.message[0].text,
- lastMessageHtml: optimisticApprovedReportAction.message[0].html,
+ lastMessageText: optimisticApprovedReportAction.message?.[0].text,
+ lastMessageHtml: optimisticApprovedReportAction.message?.[0].html,
stateNum: CONST.REPORT.STATE_NUM.APPROVED,
statusNum: CONST.REPORT.STATUS_NUM.APPROVED,
},
};
- const optimisticData = [optimisticIOUReportData, optimisticReportActionsData];
+ const optimisticData: OnyxUpdate[] = [optimisticIOUReportData, optimisticReportActionsData];
- const successData = [
+ const successData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`,
@@ -3329,19 +3293,19 @@ function approveMoneyRequest(expenseReport) {
},
];
- const failureData = [
+ const failureData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`,
value: {
- [expenseReport.reportActionID]: {
+ [expenseReport.reportActionID ?? '']: {
errors: ErrorUtils.getMicroSecondOnyxError('iou.error.other'),
},
},
},
];
- if (!_.isNull(currentNextStep)) {
+ if (currentNextStep) {
optimisticData.push({
onyxMethod: Onyx.METHOD.SET,
key: `${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport.reportID}`,
@@ -3354,27 +3318,29 @@ function approveMoneyRequest(expenseReport) {
});
}
- API.write('ApproveMoneyRequest', {reportID: expenseReport.reportID, approvedReportActionID: optimisticApprovedReportAction.reportActionID}, {optimisticData, successData, failureData});
+ const parameters: ApproveMoneyRequestParams = {
+ reportID: expenseReport.reportID,
+ approvedReportActionID: optimisticApprovedReportAction.reportActionID,
+ };
+
+ API.write(WRITE_COMMANDS.APPROVE_MONEY_REQUEST, parameters, {optimisticData, successData, failureData});
}
-/**
- * @param {Object} expenseReport
- */
-function submitReport(expenseReport) {
- const currentNextStep = lodashGet(allNextSteps, `${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport.reportID}`, null);
+function submitReport(expenseReport: OnyxTypes.Report) {
+ const currentNextStep = allNextSteps[`${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport.reportID}`] ?? null;
- const optimisticSubmittedReportAction = ReportUtils.buildOptimisticSubmittedReportAction(expenseReport.total, expenseReport.currency, expenseReport.reportID);
+ const optimisticSubmittedReportAction = ReportUtils.buildOptimisticSubmittedReportAction(expenseReport?.total ?? 0, expenseReport.currency ?? '', expenseReport.reportID);
const parentReport = ReportUtils.getReport(expenseReport.parentReportID);
const policy = ReportUtils.getPolicy(expenseReport.policyID);
const isCurrentUserManager = currentUserPersonalDetails.accountID === expenseReport.managerID;
- const optimisticData = [
+ const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`,
value: {
[optimisticSubmittedReportAction.reportActionID]: {
- ...optimisticSubmittedReportAction,
+ ...(optimisticSubmittedReportAction as OnyxTypes.ReportAction),
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
},
},
@@ -3384,30 +3350,28 @@ function submitReport(expenseReport) {
key: `${ONYXKEYS.COLLECTION.REPORT}${expenseReport.reportID}`,
value: {
...expenseReport,
- lastMessageText: lodashGet(optimisticSubmittedReportAction, 'message.0.text', ''),
- lastMessageHtml: lodashGet(optimisticSubmittedReportAction, 'message.0.html', ''),
+ lastMessageText: optimisticSubmittedReportAction.message?.[0].text ?? '',
+ lastMessageHtml: optimisticSubmittedReportAction.message?.[0].html ?? '',
stateNum: CONST.REPORT.STATE_NUM.SUBMITTED,
statusNum: CONST.REPORT.STATUS_NUM.SUBMITTED,
},
},
- ...(parentReport.reportID
- ? [
- {
- onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT}${parentReport.reportID}`,
- value: {
- ...parentReport,
-
- // In case its a manager who force submitted the report, they are the next user who needs to take an action
- hasOutstandingChildRequest: isCurrentUserManager,
- iouReportID: null,
- },
- },
- ]
- : []),
];
- const successData = [
+ if (parentReport?.reportID) {
+ optimisticData.push({
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${parentReport.reportID}`,
+ value: {
+ ...parentReport,
+ // In case its a manager who force submitted the report, they are the next user who needs to take an action
+ hasOutstandingChildRequest: isCurrentUserManager,
+ iouReportID: null,
+ },
+ });
+ }
+
+ const successData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`,
@@ -3419,7 +3383,7 @@ function submitReport(expenseReport) {
},
];
- const failureData = [
+ const failureData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`,
@@ -3437,21 +3401,20 @@ function submitReport(expenseReport) {
stateNum: CONST.REPORT.STATE_NUM.OPEN,
},
},
- ...(parentReport.reportID
- ? [
- {
- onyxMethod: Onyx.METHOD.MERGE,
- key: `${ONYXKEYS.COLLECTION.REPORT}${parentReport.reportID}`,
- value: {
- hasOutstandingChildRequest: parentReport.hasOutstandingChildRequest,
- iouReportID: expenseReport.reportID,
- },
- },
- ]
- : []),
];
- if (!_.isNull(currentNextStep)) {
+ if (parentReport?.reportID) {
+ failureData.push({
+ onyxMethod: Onyx.METHOD.MERGE,
+ key: `${ONYXKEYS.COLLECTION.REPORT}${parentReport.reportID}`,
+ value: {
+ hasOutstandingChildRequest: parentReport.hasOutstandingChildRequest,
+ iouReportID: expenseReport.reportID,
+ },
+ });
+ }
+
+ if (currentNextStep) {
optimisticData.push({
onyxMethod: Onyx.METHOD.SET,
key: `${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport.reportID}`,
@@ -3464,40 +3427,32 @@ function submitReport(expenseReport) {
});
}
- API.write(
- 'SubmitReport',
- {
- reportID: expenseReport.reportID,
- managerAccountID: policy.submitsTo || expenseReport.managerID,
- reportActionID: optimisticSubmittedReportAction.reportActionID,
- },
- {optimisticData, successData, failureData},
- );
+ const parameters: SubmitReportParams = {
+ reportID: expenseReport.reportID,
+ managerAccountID: policy.submitsTo ?? expenseReport.managerID,
+ reportActionID: optimisticSubmittedReportAction.reportActionID,
+ };
+
+ API.write(WRITE_COMMANDS.SUBMIT_REPORT, parameters, {optimisticData, successData, failureData});
}
-/**
- * @param {String} paymentType
- * @param {Object} chatReport
- * @param {Object} iouReport
- * @param {String} reimbursementBankAccountState
- */
-function payMoneyRequest(paymentType, chatReport, iouReport) {
+function payMoneyRequest(paymentType: PaymentMethodType, chatReport: OnyxTypes.Report, iouReport: OnyxTypes.Report) {
const recipient = {accountID: iouReport.ownerAccountID};
const {params, optimisticData, successData, failureData} = getPayMoneyRequestParams(chatReport, iouReport, recipient, paymentType);
// For now we need to call the PayMoneyRequestWithWallet API since PayMoneyRequest was not updated to work with
// Expensify Wallets.
- const apiCommand = paymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY ? 'PayMoneyRequestWithWallet' : 'PayMoneyRequest';
+ const apiCommand = paymentType === CONST.IOU.PAYMENT_TYPE.EXPENSIFY ? WRITE_COMMANDS.PAY_MONEY_REQUEST_WITH_WALLET : WRITE_COMMANDS.PAY_MONEY_REQUEST;
API.write(apiCommand, params, {optimisticData, successData, failureData});
Navigation.dismissModalWithReport(chatReport);
}
-function detachReceipt(transactionID) {
- const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`] || {};
- const newTransaction = {...transaction, filename: '', receipt: {}};
+function detachReceipt(transactionID: string) {
+ const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`];
+ const newTransaction = transaction ? {...transaction, filename: '', receipt: {}} : null;
- const optimisticData = [
+ const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.SET,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
@@ -3505,7 +3460,7 @@ function detachReceipt(transactionID) {
},
];
- const failureData = [
+ const failureData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
@@ -3513,22 +3468,20 @@ function detachReceipt(transactionID) {
},
];
- API.write('DetachReceipt', {transactionID}, {optimisticData, failureData});
+ const parameters: DetachReceiptParams = {transactionID};
+
+ API.write(WRITE_COMMANDS.DETACH_RECEIPT, parameters, {optimisticData, failureData});
}
-/**
- * @param {String} transactionID
- * @param {Object} file
- * @param {String} source
- */
-function replaceReceipt(transactionID, file, source) {
- const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`] || {};
- const oldReceipt = lodashGet(transaction, 'receipt', {});
+function replaceReceipt(transactionID: string, file: File, source: string) {
+ const transaction = allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`];
+ const oldReceipt = transaction?.receipt ?? {};
const receiptOptimistic = {
source,
state: CONST.IOU.RECEIPT_STATE.OPEN,
};
- const optimisticData = [
+
+ const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
@@ -3539,95 +3492,73 @@ function replaceReceipt(transactionID, file, source) {
},
];
- const failureData = [
+ const failureData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`,
value: {
receipt: oldReceipt,
- filename: transaction.filename,
+ filename: transaction?.filename,
errors: getReceiptError(receiptOptimistic, file.name),
},
},
];
- API.write('ReplaceReceipt', {transactionID, receipt: file}, {optimisticData, failureData});
+ const parameters: ReplaceReceiptParams = {
+ transactionID,
+ receipt: file,
+ };
+
+ API.write(WRITE_COMMANDS.REPLACE_RECEIPT, parameters, {optimisticData, failureData});
}
/**
* Finds the participants for an IOU based on the attached report
- * @param {String} transactionID of the transaction to set the participants of
- * @param {Object} report attached to the transaction
+ * @param transactionID of the transaction to set the participants of
+ * @param report attached to the transaction
*/
-function setMoneyRequestParticipantsFromReport(transactionID, report) {
+function setMoneyRequestParticipantsFromReport(transactionID: string, report: OnyxTypes.Report) {
// If the report is iou or expense report, we should get the chat report to set participant for request money
const chatReport = ReportUtils.isMoneyRequestReport(report) ? ReportUtils.getReport(report.chatReportID) : report;
const currentUserAccountID = currentUserPersonalDetails.accountID;
- const participants = ReportUtils.isPolicyExpenseChat(chatReport)
- ? [{reportID: chatReport.reportID, isPolicyExpenseChat: true, selected: true}]
- : _.chain(chatReport.participantAccountIDs)
- .filter((accountID) => currentUserAccountID !== accountID)
- .map((accountID) => ({accountID, selected: true}))
- .value();
+ const participants: Participant[] = ReportUtils.isPolicyExpenseChat(chatReport)
+ ? [{reportID: chatReport?.reportID, isPolicyExpenseChat: true, selected: true}]
+ : (chatReport?.participantAccountIDs ?? []).filter((accountID) => currentUserAccountID !== accountID).map((accountID) => ({accountID, selected: true}));
+
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {participants, participantsAutoAssigned: true});
}
-/**
- * Initialize money request info and navigate to the MoneyRequest page
- * @param {String} iouType
- * @param {String} reportID
- */
-function startMoneyRequest(iouType, reportID = '') {
+/** Initialize money request info and navigate to the MoneyRequest page */
+function startMoneyRequest(iouType: string, reportID = '') {
resetMoneyRequestInfo(`${iouType}${reportID}`);
Navigation.navigate(ROUTES.MONEY_REQUEST.getRoute(iouType, reportID));
}
-/**
- * @param {String} id
- */
-function setMoneyRequestId(id) {
+function setMoneyRequestId(id: string) {
Onyx.merge(ONYXKEYS.IOU, {id});
}
-/**
- * @param {Number} amount
- */
-function setMoneyRequestAmount(amount) {
+function setMoneyRequestAmount(amount: number) {
Onyx.merge(ONYXKEYS.IOU, {amount});
}
-/**
- * @param {String} created
- */
-function setMoneyRequestCreated(created) {
+function setMoneyRequestCreated(created: string) {
Onyx.merge(ONYXKEYS.IOU, {created});
}
-/**
- * @param {String} currency
- */
-function setMoneyRequestCurrency(currency) {
+function setMoneyRequestCurrency(currency: string) {
Onyx.merge(ONYXKEYS.IOU, {currency});
}
-/**
- * @param {String} comment
- */
-function setMoneyRequestDescription(comment) {
+function setMoneyRequestDescription(comment: string) {
Onyx.merge(ONYXKEYS.IOU, {comment: comment.trim()});
}
-/**
- * @param {String} merchant
- */
-function setMoneyRequestMerchant(merchant) {
+function setMoneyRequestMerchant(merchant: string) {
Onyx.merge(ONYXKEYS.IOU, {merchant: merchant.trim()});
}
-/**
- * @param {String} category
- */
-function setMoneyRequestCategory(category) {
+function setMoneyRequestCategory(category: string) {
Onyx.merge(ONYXKEYS.IOU, {category});
}
@@ -3635,45 +3566,19 @@ function resetMoneyRequestCategory() {
Onyx.merge(ONYXKEYS.IOU, {category: ''});
}
-/*
- * @param {String} tag
- */
-function setMoneyRequestTag(tag) {
- Onyx.merge(ONYXKEYS.IOU, {tag});
-}
-
-function resetMoneyRequestTag() {
- Onyx.merge(ONYXKEYS.IOU, {tag: ''});
-}
-
-/**
- * @param {String} transactionID
- * @param {Object} taxRate
- */
-function setMoneyRequestTaxRate(transactionID, taxRate) {
+function setMoneyRequestTaxRate(transactionID: string, taxRate: TaxRate) {
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {taxRate});
}
-/**
- * @param {String} transactionID
- * @param {Number} taxAmount
- */
-function setMoneyRequestTaxAmount(transactionID, taxAmount) {
+function setMoneyRequestTaxAmount(transactionID: string, taxAmount: number) {
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {taxAmount});
}
-/**
- * @param {Boolean} billable
- */
-function setMoneyRequestBillable(billable) {
+function setMoneyRequestBillable(billable: boolean) {
Onyx.merge(ONYXKEYS.IOU, {billable});
}
-/**
- * @param {Object[]} participants
- * @param {Boolean} isSplitRequest
- */
-function setMoneyRequestParticipants(participants, isSplitRequest) {
+function setMoneyRequestParticipants(participants: Participant[], isSplitRequest?: boolean) {
Onyx.merge(ONYXKEYS.IOU, {participants, isSplitRequest});
}
@@ -3686,18 +3591,10 @@ function setUpDistanceTransaction() {
Onyx.merge(ONYXKEYS.IOU, {transactionID});
}
-/**
- * Navigates to the next IOU page based on where the IOU request was started
- *
- * @param {Object} iou
- * @param {String} iouType
- * @param {Object} report
- * @param {String} report.reportID
- * @param {String} path
- */
-function navigateToNextPage(iou, iouType, report, path = '') {
- const moneyRequestID = `${iouType}${report.reportID || ''}`;
- const shouldReset = iou.id !== moneyRequestID && !_.isEmpty(report.reportID);
+/** Navigates to the next IOU page based on where the IOU request was started */
+function navigateToNextPage(iou: OnyxEntry, iouType: string, report?: OnyxTypes.Report, path = '') {
+ const moneyRequestID = `${iouType}${report?.reportID ?? ''}`;
+ const shouldReset = iou?.id !== moneyRequestID && !!report?.reportID;
// If the money request ID in Onyx does not match the ID from params, we want to start a new request
// with the ID from params. We need to clear the participants in case the new request is initiated from FAB.
@@ -3706,27 +3603,23 @@ function navigateToNextPage(iou, iouType, report, path = '') {
}
// If we're adding a receipt, that means the user came from the confirmation page and we need to navigate back to it.
- if (path.slice(1) === ROUTES.MONEY_REQUEST_RECEIPT.getRoute(iouType, report.reportID)) {
- Navigation.navigate(ROUTES.MONEY_REQUEST_CONFIRMATION.getRoute(iouType, report.reportID));
+ if (path.slice(1) === ROUTES.MONEY_REQUEST_RECEIPT.getRoute(iouType, report?.reportID)) {
+ Navigation.navigate(ROUTES.MONEY_REQUEST_CONFIRMATION.getRoute(iouType, report?.reportID));
return;
}
// If a request is initiated on a report, skip the participants selection step and navigate to the confirmation page.
- if (report.reportID) {
+ if (report?.reportID) {
// If the report is iou or expense report, we should get the chat report to set participant for request money
const chatReport = ReportUtils.isMoneyRequestReport(report) ? ReportUtils.getReport(report.chatReportID) : report;
// Reinitialize the participants when the money request ID in Onyx does not match the ID from params
- if (_.isEmpty(iou.participants) || shouldReset) {
+ if (!iou?.participants?.length || shouldReset) {
const currentUserAccountID = currentUserPersonalDetails.accountID;
- const participants = ReportUtils.isPolicyExpenseChat(chatReport)
- ? [{reportID: chatReport.reportID, isPolicyExpenseChat: true, selected: true}]
- : _.chain(chatReport.participantAccountIDs)
- .filter((accountID) => currentUserAccountID !== accountID)
- .map((accountID) => ({accountID, selected: true}))
- .value();
+ const participants: Participant[] = ReportUtils.isPolicyExpenseChat(chatReport)
+ ? [{reportID: chatReport?.reportID, isPolicyExpenseChat: true, selected: true}]
+ : (chatReport?.participantAccountIDs ?? []).filter((accountID) => currentUserAccountID !== accountID).map((accountID) => ({accountID, selected: true}));
setMoneyRequestParticipants(participants);
resetMoneyRequestCategory();
- resetMoneyRequestTag();
}
Navigation.navigate(ROUTES.MONEY_REQUEST_CONFIRMATION.getRoute(iouType, report.reportID));
return;
@@ -3738,28 +3631,23 @@ function navigateToNextPage(iou, iouType, report, path = '') {
* When the money request or split bill creation flow is initialized via FAB, the reportID is not passed as a navigation
* parameter.
* Gets a report id from the first participant of the IOU object stored in Onyx.
- * @param {Object} iou
- * @param {Array} iou.participants
- * @param {Object} route
- * @param {Object} route.params
- * @param {String} [route.params.reportID]
- * @returns {String}
*/
-function getIOUReportID(iou, route) {
- return lodashGet(route, 'params.reportID') || lodashGet(iou, 'participants.0.reportID', '');
+function getIOUReportID(iou?: OnyxTypes.IOU, route?: MoneyRequestRoute): string {
+ // Disabling this line for safeness as nullish coalescing works only if the value is undefined or null
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
+ return route?.params.reportID || iou?.participants?.[0]?.reportID || '';
}
-/**
- * @param {String} receiptFilename
- * @param {String} receiptPath
- * @param {Function} onSuccess
- * @param {String} requestType
- * @param {String} iouType
- * @param {String} transactionID
- * @param {String} reportID
- */
// eslint-disable-next-line rulesdir/no-negated-variables
-function navigateToStartStepIfScanFileCannotBeRead(receiptFilename, receiptPath, onSuccess, requestType, iouType, transactionID, reportID) {
+function navigateToStartStepIfScanFileCannotBeRead(
+ receiptFilename: string,
+ receiptPath: string,
+ onSuccess: (file: File) => void,
+ requestType: ValueOf,
+ iouType: ValueOf,
+ transactionID: string,
+ reportID: string,
+) {
if (!receiptFilename || !receiptPath) {
return;
}
@@ -3775,12 +3663,8 @@ function navigateToStartStepIfScanFileCannotBeRead(receiptFilename, receiptPath,
FileUtils.readFileAsync(receiptPath, receiptFilename, onSuccess, onFailure);
}
-/**
- * Save the preferred payment method for a policy
- * @param {String} policyID
- * @param {String} paymentMethod
- */
-function savePreferredPaymentMethod(policyID, paymentMethod) {
+/** Save the preferred payment method for a policy */
+function savePreferredPaymentMethod(policyID: string, paymentMethod: PaymentMethodType) {
Onyx.merge(`${ONYXKEYS.NVP_LAST_PAYMENT_METHOD}`, {[policyID]: paymentMethod});
}
@@ -3804,19 +3688,17 @@ export {
resetMoneyRequestCategory,
resetMoneyRequestCategory_temporaryForRefactor,
resetMoneyRequestInfo,
- resetMoneyRequestTag,
- resetMoneyRequestTag_temporaryForRefactor,
clearMoneyRequest,
setMoneyRequestAmount_temporaryForRefactor,
setMoneyRequestBillable_temporaryForRefactor,
setMoneyRequestCategory_temporaryForRefactor,
setMoneyRequestCreated_temporaryForRefactor,
setMoneyRequestCurrency_temporaryForRefactor,
+ setMoneyRequestOriginalCurrency_temporaryForRefactor,
setMoneyRequestDescription_temporaryForRefactor,
setMoneyRequestMerchant_temporaryForRefactor,
setMoneyRequestParticipants_temporaryForRefactor,
setMoneyRequestReceipt,
- setMoneyRequestTag_temporaryForRefactor,
setMoneyRequestAmount,
setMoneyRequestBillable,
setMoneyRequestCategory,
diff --git a/src/libs/actions/PaymentMethods.ts b/src/libs/actions/PaymentMethods.ts
index cbc5778187a1..2199c5768612 100644
--- a/src/libs/actions/PaymentMethods.ts
+++ b/src/libs/actions/PaymentMethods.ts
@@ -3,7 +3,6 @@ import type {MutableRefObject} from 'react';
import type {GestureResponderEvent} from 'react-native';
import type {OnyxEntry, OnyxUpdate} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
-import type {TransferMethod} from '@components/KYCWall/types';
import * as API from '@libs/API';
import type {AddPaymentCardParams, DeletePaymentCardParams, MakeDefaultPaymentMethodParams, PaymentCardParams, TransferWalletBalanceParams} from '@libs/API/parameters';
import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
@@ -14,11 +13,12 @@ import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {Route} from '@src/ROUTES';
import type {BankAccountList, FundList} from '@src/types/onyx';
+import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage';
import type PaymentMethod from '@src/types/onyx/PaymentMethod';
import type {FilterMethodPaymentType} from '@src/types/onyx/WalletTransfer';
type KYCWallRef = {
- continueAction?: (event?: GestureResponderEvent | KeyboardEvent, iouPaymentType?: TransferMethod) => void;
+ continueAction?: (event?: GestureResponderEvent | KeyboardEvent, iouPaymentType?: PaymentMethodType) => void;
};
/**
diff --git a/src/libs/actions/PersonalDetails.ts b/src/libs/actions/PersonalDetails.ts
index ac044b0bc25b..26c8937de3aa 100644
--- a/src/libs/actions/PersonalDetails.ts
+++ b/src/libs/actions/PersonalDetails.ts
@@ -1,4 +1,3 @@
-import Str from 'expensify-common/lib/str';
import type {OnyxEntry, OnyxUpdate} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
import * as API from '@libs/API';
@@ -16,7 +15,6 @@ import type {
import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
import type {CustomRNImageManipulatorResult} from '@libs/cropOrRotateImage/types';
import DateUtils from '@libs/DateUtils';
-import * as LocalePhoneNumber from '@libs/LocalePhoneNumber';
import Navigation from '@libs/Navigation/Navigation';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import * as UserUtils from '@libs/UserUtils';
@@ -27,11 +25,6 @@ import type {DateOfBirthForm, PersonalDetails, PersonalDetailsList, PrivatePerso
import type {SelectedTimezone, Timezone} from '@src/types/onyx/PersonalDetails';
import * as Session from './Session';
-type FirstAndLastName = {
- firstName: string;
- lastName: string;
-};
-
let currentUserEmail = '';
let currentUserAccountID = -1;
Onyx.connect({
@@ -54,69 +47,6 @@ Onyx.connect({
callback: (val) => (privatePersonalDetails = val),
});
-/**
- * Creates a new displayName for a user based on passed personal details or login.
- */
-function createDisplayName(login: string, personalDetails: Pick | OnyxEntry): string {
- // If we have a number like +15857527441@expensify.sms then let's remove @expensify.sms and format it
- // so that the option looks cleaner in our UI.
- const userLogin = LocalePhoneNumber.formatPhoneNumber(login);
-
- if (!personalDetails) {
- return userLogin;
- }
-
- const firstName = personalDetails.firstName ?? '';
- const lastName = personalDetails.lastName ?? '';
- const fullName = `${firstName} ${lastName}`.trim();
-
- // It's possible for fullName to be empty string, so we must use "||" to fallback to userLogin.
- return fullName || userLogin;
-}
-
-/**
- * Gets the first and last name from the user's personal details.
- * If the login is the same as the displayName, then they don't exist,
- * so we return empty strings instead.
- */
-function extractFirstAndLastNameFromAvailableDetails({login, displayName, firstName, lastName}: PersonalDetails): FirstAndLastName {
- // It's possible for firstName to be empty string, so we must use "||" to consider lastName instead.
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
- if (firstName || lastName) {
- return {firstName: firstName ?? '', lastName: lastName ?? ''};
- }
- if (login && Str.removeSMSDomain(login) === displayName) {
- return {firstName: '', lastName: ''};
- }
-
- if (displayName) {
- const firstSpaceIndex = displayName.indexOf(' ');
- const lastSpaceIndex = displayName.lastIndexOf(' ');
- if (firstSpaceIndex === -1) {
- return {firstName: displayName, lastName: ''};
- }
-
- return {
- firstName: displayName.substring(0, firstSpaceIndex).trim(),
- lastName: displayName.substring(lastSpaceIndex).trim(),
- };
- }
-
- return {firstName: '', lastName: ''};
-}
-
-/**
- * Convert country names obtained from the backend to their respective ISO codes
- * This is for backward compatibility of stored data before E/App#15507
- */
-function getCountryISO(countryName: string): string {
- if (!countryName || countryName.length === 2) {
- return countryName;
- }
-
- return Object.entries(CONST.ALL_COUNTRIES).find(([, value]) => value === countryName)?.[0] ?? '';
-}
-
function updatePronouns(pronouns: string) {
if (currentUserAccountID) {
const parameters: UpdatePronounsParams = {pronouns};
@@ -152,7 +82,7 @@ function updateDisplayName(firstName: string, lastName: string) {
[currentUserAccountID]: {
firstName,
lastName,
- displayName: createDisplayName(currentUserEmail ?? '', {
+ displayName: PersonalDetailsUtils.createDisplayName(currentUserEmail ?? '', {
firstName,
lastName,
}),
@@ -524,9 +454,6 @@ function getPrivatePersonalDetails(): OnyxEntry