Skip to content
Merged
13 changes: 7 additions & 6 deletions src/hooks/useParticipantSubmission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,12 +320,13 @@ function useParticipantSubmission({
if ((isCategorizing || isShareAction) && numberOfParticipants.current === 0) {
const email = userDetails.email ?? '';
const lastWorkspaceNumber = lastWorkspaceNumberSelector(policies, email);
const {expenseChatReportID, policyID, policyName} = createDraftWorkspace(
intro,
generateDefaultWorkspaceName(email, lastWorkspaceNumber, translate),
userDetails.accountID,
email,
);
const {expenseChatReportID, policyID, policyName} = createDraftWorkspace({
introSelected: intro,
workspaceName: generateDefaultWorkspaceName(email, lastWorkspaceNumber, translate),
currentUserAccountID: userDetails.accountID,
currentUserEmail: email,
currency: userDetails.localCurrencyCode ?? CONST.CURRENCY.USD,
});
for (const transaction of drafts) {
setMoneyRequestParticipants(transaction.transactionID, [
{
Expand Down
13 changes: 11 additions & 2 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11258,9 +11258,16 @@ function createDraftWorkspaceAndNavigateToConfirmationScreen(
workspaceName: string,
currentUserAccountID: number,
currentUserEmail: string,
currentUserLocalCurrency: string,
): void {
const isCategorizing = actionName === CONST.IOU.ACTION.CATEGORIZE;
const {expenseChatReportID, policyID, policyName} = createDraftWorkspace(introSelected, workspaceName, currentUserAccountID, currentUserEmail);
const {expenseChatReportID, policyID, policyName} = createDraftWorkspace({
introSelected,
workspaceName,
currentUserAccountID,
currentUserEmail,
currency: currentUserLocalCurrency,
});
setMoneyRequestParticipants(transactionID, [
{
selected: true,
Expand Down Expand Up @@ -11294,6 +11301,7 @@ type CreateDraftTransactionParams = {
transaction: OnyxEntry<Transaction>;
currentUserAccountID: number;
currentUserEmail: string;
currentUserLocalCurrency: string;
};

function createDraftTransactionAndNavigateToParticipantSelector({
Expand All @@ -11311,6 +11319,7 @@ function createDraftTransactionAndNavigateToParticipantSelector({
transaction,
currentUserAccountID,
currentUserEmail,
currentUserLocalCurrency,
}: CreateDraftTransactionParams): void {
const transactionID = transaction?.transactionID;
if (!transactionID || !reportID) {
Expand Down Expand Up @@ -11455,7 +11464,7 @@ function createDraftTransactionAndNavigateToParticipantSelector({
return;
}

return createDraftWorkspaceAndNavigateToConfirmationScreen(introSelected, transactionID, actionName, '', currentUserAccountID, currentUserEmail);
return createDraftWorkspaceAndNavigateToConfirmationScreen(introSelected, transactionID, actionName, '', currentUserAccountID, currentUserEmail, currentUserLocalCurrency);
}

/**
Expand Down
31 changes: 22 additions & 9 deletions src/libs/actions/Policy/Policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3067,17 +3067,29 @@ function createWorkspace(options: CreateWorkspaceDataOptions): CreateWorkspacePa
/**
* Creates a draft workspace for various money request flows
*/
function createDraftWorkspace(
introSelected: OnyxEntry<IntroSelected>,
workspaceName: string,
currentUserAccountID: number,
currentUserEmail: string,
type CreateDraftWorkspaceParams = {
introSelected: OnyxEntry<IntroSelected>;
workspaceName: string;
currentUserAccountID: number;
currentUserEmail: string;
policyOwnerEmail?: string;
makeMeAdmin?: boolean;
policyID?: string;
currency?: string;
file?: File;
};

function createDraftWorkspace({
introSelected,
workspaceName,
currentUserAccountID,
currentUserEmail,
policyOwnerEmail = '',
makeMeAdmin = false,
policyID = generatePolicyID(),
currency = '',
file?: File,
): CreateWorkspaceParams {
file,
}: CreateDraftWorkspaceParams): CreateWorkspaceParams {
const {customUnits, customUnitID, customUnitRateID, outputCurrency} = buildOptimisticDistanceRateCustomUnits(currency);

const {expenseChatData, adminsChatReportID, adminsCreatedReportActionID, expenseChatReportID, expenseCreatedReportActionID} = ReportUtils.buildOptimisticWorkspaceChats(
Expand Down Expand Up @@ -3234,7 +3246,7 @@ function buildDuplicatePolicyData(policy: Policy, options: DuplicatePolicyDataOp
const isTravelOptionSelected = parts?.travel;
const isCodingRulesOptionSelected = parts?.codingRules;

const outputCurrency = isOverviewOptionSelected ? policy?.outputCurrency : localCurrency;
const outputCurrency = isOverviewOptionSelected && policy?.outputCurrency ? policy?.outputCurrency : localCurrency;

const policyMemberAccountIDs = isMemberOptionSelected ? Object.values(getMemberAccountIDsForWorkspace(policy?.employeeList, false, false)) : [];
const {customUnitID: distanceCustomUnitID, customUnitRateID} = buildOptimisticDistanceRateCustomUnits(outputCurrency);
Expand Down Expand Up @@ -4061,7 +4073,8 @@ function createWorkspaceFromIOUPayment(
const policyID = generatePolicyID();
const workspaceName = generateDefaultWorkspaceName(currentUserEmail, lastWorkspaceNumber, localeTranslate);
const employeeAccountID = iouReport?.ownerAccountID;
const {customUnits, customUnitID, customUnitRateID} = buildOptimisticDistanceRateCustomUnits(iouReport?.currency ?? currentUserLocalCurrency);
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- Disabling this line for safeness as iouReport?.currency could be an empty string
const {customUnits, customUnitID, customUnitRateID} = buildOptimisticDistanceRateCustomUnits(iouReport?.currency || currentUserLocalCurrency);
const oldPersonalPolicyID = iouReport?.policyID;
const iouReportID = iouReport?.reportID;

Expand Down
5 changes: 5 additions & 0 deletions src/pages/ReportDetailsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata, reportLoading
const actionReportID = getOriginalReportID(report.reportID, parentReportAction, reportActionsForOriginalReportID);
const whisperAction = getTrackExpenseActionableWhisper(iouTransactionID, moneyRequestReport?.reportID);
const actionableWhisperReportActionID = whisperAction?.reportActionID;
const currentUserLocalCurrency = currentUserPersonalDetails.localCurrencyCode ?? CONST.CURRENCY.USD;
items.push({
key: CONST.REPORT_DETAILS_MENU_ITEM.TRACK.SUBMIT,
translationKey: 'actionableMentionTrackExpense.submit',
Expand All @@ -476,6 +477,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata, reportLoading
transaction: iouTransaction,
currentUserAccountID: currentUserPersonalDetails.accountID,
currentUserEmail: currentUserPersonalDetails.email ?? '',
currentUserLocalCurrency,
});
},
});
Expand All @@ -500,6 +502,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata, reportLoading
transaction: iouTransaction,
currentUserAccountID: currentUserPersonalDetails.accountID,
currentUserEmail: currentUserPersonalDetails.email ?? '',
currentUserLocalCurrency,
});
},
});
Expand All @@ -523,6 +526,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata, reportLoading
transaction: iouTransaction,
currentUserAccountID: currentUserPersonalDetails.accountID,
currentUserEmail: currentUserPersonalDetails.email ?? '',
currentUserLocalCurrency,
});
},
});
Expand Down Expand Up @@ -638,6 +642,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata, reportLoading
moneyRequestReport?.reportID,
currentUserPersonalDetails.accountID,
currentUserPersonalDetails.email,
currentUserPersonalDetails.localCurrencyCode,
isTaskActionable,
isRootGroupChat,
leaveChat,
Expand Down
19 changes: 9 additions & 10 deletions src/pages/Travel/WorkspaceConfirmationForTravelPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import useOnyx from '@hooks/useOnyx';
import {createDraftWorkspace, createWorkspace} from '@libs/actions/Policy/Policy';
import Navigation from '@libs/Navigation/Navigation';
import type {TravelNavigatorParamList} from '@libs/Navigation/types';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type SCREENS from '@src/SCREENS';
Expand All @@ -30,17 +31,15 @@ function WorkspaceConfirmationForTravelPage({route}: WorkspaceConfirmationForTra
};

const onSubmit = (params: WorkspaceConfirmationSubmitFunctionParams) => {
createDraftWorkspace(
createDraftWorkspace({
introSelected,
params.name,
currentUserPersonalDetails.accountID,
currentUserPersonalDetails.email ?? '',
'',
false,
params.policyID,
params.currency,
params.avatarFile as File,
);
workspaceName: params.name,
currentUserAccountID: currentUserPersonalDetails.accountID,
currentUserEmail: currentUserPersonalDetails.email ?? '',
policyID: params.policyID,
currency: params.currency || (currentUserPersonalDetails.localCurrencyCode ?? CONST.CURRENCY.USD),
file: params.avatarFile as File,
});
createWorkspace({
policyName: params.name,
policyID: params.policyID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ function ChatActionableButtons({action, report, originalReport, reportID, origin
transaction: trackExpenseTransaction,
currentUserAccountID: personalDetail.accountID,
currentUserEmail: personalDetail.email ?? '',
currentUserLocalCurrency: personalDetail.localCurrencyCode ?? CONST.CURRENCY.USD,
};
const TRACK_EXPENSE_ACTIONS = {
submit: CONST.IOU.ACTION.SUBMIT,
Expand Down
15 changes: 11 additions & 4 deletions src/pages/iou/request/step/IOURequestStepAccountant.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {generateDefaultWorkspaceName} from '@libs/actions/Policy/Policy';
import Navigation from '@libs/Navigation/Navigation';
import {createDraftWorkspaceAndNavigateToConfirmationScreen} from '@libs/ReportUtils';
import MoneyRequestAccountantSelector from '@pages/iou/request/MoneyRequestAccountantSelector';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type SCREENS from '@src/SCREENS';
Expand All @@ -26,11 +27,9 @@ function IOURequestStepAccountant({
},
}: IOURequestStepAccountantProps) {
const {translate} = useLocalize();
const {accountID, login, email = ''} = useCurrentUserPersonalDetails();

const {accountID, login, email = '', localCurrencyCode} = useCurrentUserPersonalDetails();
const selector = (policies: OnyxCollection<Policy>) => activeAdminPoliciesSelector(policies, login ?? '');
const lastWorkspaceNumberWithEmailSelector = (policies: OnyxCollection<Policy>) => lastWorkspaceNumberSelector(policies, email);

const [adminPolicies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {selector});
const [lastWorkspaceNumber] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {selector: lastWorkspaceNumberWithEmailSelector});
const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
Expand All @@ -43,7 +42,15 @@ function IOURequestStepAccountant({
// Sharing with an accountant involves inviting them to the workspace and that requires admin access.
const hasActiveAdminWorkspaces = (adminPolicies?.length ?? 0) > 0;
if (!hasActiveAdminWorkspaces) {
createDraftWorkspaceAndNavigateToConfirmationScreen(introSelected, transactionID, action, generateDefaultWorkspaceName(email, lastWorkspaceNumber, translate), accountID, email);
createDraftWorkspaceAndNavigateToConfirmationScreen(
introSelected,
transactionID,
action,
generateDefaultWorkspaceName(email, lastWorkspaceNumber, translate),
accountID,
email,
localCurrencyCode ?? CONST.CURRENCY.USD,
);
return;
}

Expand Down
4 changes: 4 additions & 0 deletions tests/actions/IOUTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ describe('actions/IOU', () => {
transaction: transactionToCategorize,
currentUserAccountID: RORY_ACCOUNT_ID,
currentUserEmail: RORY_EMAIL,
currentUserLocalCurrency: '',
});
await waitForBatchedUpdates();

Expand Down Expand Up @@ -534,6 +535,7 @@ describe('actions/IOU', () => {
transaction: originalTransaction,
currentUserAccountID: RORY_ACCOUNT_ID,
currentUserEmail: RORY_EMAIL,
currentUserLocalCurrency: '',
});
await waitForBatchedUpdates();

Expand Down Expand Up @@ -573,6 +575,7 @@ describe('actions/IOU', () => {
transaction: undefined,
currentUserAccountID: RORY_ACCOUNT_ID,
currentUserEmail: RORY_EMAIL,
currentUserLocalCurrency: '',
});
await waitForBatchedUpdates();

Expand Down Expand Up @@ -607,6 +610,7 @@ describe('actions/IOU', () => {
amountOwed: 0,
currentUserAccountID: RORY_ACCOUNT_ID,
currentUserEmail: RORY_EMAIL,
currentUserLocalCurrency: '',
});
await waitForBatchedUpdates();

Expand Down
2 changes: 2 additions & 0 deletions tests/actions/IOUTest/TrackExpenseTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ describe('actions/IOU/TrackExpense', () => {
transaction,
currentUserAccountID: RORY_ACCOUNT_ID,
currentUserEmail: RORY_EMAIL,
currentUserLocalCurrency: '',
});
await waitForBatchedUpdates();

Expand Down Expand Up @@ -1114,6 +1115,7 @@ describe('actions/IOU/TrackExpense', () => {
transaction: createdTransaction,
currentUserAccountID: RORY_ACCOUNT_ID,
currentUserEmail: RORY_EMAIL,
currentUserLocalCurrency: '',
});
await waitForBatchedUpdates();

Expand Down
64 changes: 53 additions & 11 deletions tests/actions/PolicyTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2452,16 +2452,16 @@ describe('actions/Policy', () => {
await waitForBatchedUpdates();

const policyID = Policy.generatePolicyID();
const params = Policy.createDraftWorkspace(
{choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM},
WORKSPACE_NAME,
ESH_ACCOUNT_ID,
ESH_EMAIL,
ESH_EMAIL,
true,
const params = Policy.createDraftWorkspace({
introSelected: {choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM},
workspaceName: WORKSPACE_NAME,
currentUserAccountID: ESH_ACCOUNT_ID,
currentUserEmail: ESH_EMAIL,
policyOwnerEmail: ESH_EMAIL,
makeMeAdmin: true,
policyID,
CONST.CURRENCY.USD,
);
currency: CONST.CURRENCY.USD,
});
await waitForBatchedUpdates();

const draft = await getOnyxValue(`${ONYXKEYS.COLLECTION.POLICY_DRAFTS}${policyID}`);
Expand Down Expand Up @@ -2489,7 +2489,15 @@ describe('actions/Policy', () => {
await waitForBatchedUpdates();

const policyID = Policy.generatePolicyID();
Policy.createDraftWorkspace({choice: CONST.ONBOARDING_CHOICES.TRACK_WORKSPACE}, WORKSPACE_NAME, ESH_ACCOUNT_ID, ESH_EMAIL, ESH_EMAIL, false, policyID, CONST.CURRENCY.EUR);
Policy.createDraftWorkspace({
introSelected: {choice: CONST.ONBOARDING_CHOICES.TRACK_WORKSPACE},
workspaceName: WORKSPACE_NAME,
currentUserAccountID: ESH_ACCOUNT_ID,
currentUserEmail: ESH_EMAIL,
policyOwnerEmail: ESH_EMAIL,
policyID,
currency: CONST.CURRENCY.EUR,
});
await waitForBatchedUpdates();

const draft = await getOnyxValue(`${ONYXKEYS.COLLECTION.POLICY_DRAFTS}${policyID}`);
Expand All @@ -2510,7 +2518,14 @@ describe('actions/Policy', () => {
const customEmail = 'custom@example.com';
const policyID = Policy.generatePolicyID();

Policy.createDraftWorkspace({choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM}, WORKSPACE_NAME, customAccountID, customEmail, customEmail, false, policyID);
Policy.createDraftWorkspace({
introSelected: {choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM},
workspaceName: WORKSPACE_NAME,
currentUserAccountID: customAccountID,
currentUserEmail: customEmail,
policyOwnerEmail: customEmail,
policyID,
});
await waitForBatchedUpdates();

const draft = await getOnyxValue(`${ONYXKEYS.COLLECTION.POLICY_DRAFTS}${policyID}`);
Expand All @@ -2531,6 +2546,33 @@ describe('actions/Policy', () => {
expect(draft?.ownerAccountID).not.toBe(ESH_ACCOUNT_ID);
expect(draft?.employeeList?.[ESH_EMAIL]).toBeUndefined();
});

it('should use the explicit currency argument and not fall back to the deprecated session user localCurrencyCode', async () => {
// Set Onyx session + personal details so localCurrencyCode would be EUR if the fallback were used
await Onyx.set(ONYXKEYS.SESSION, {email: ESH_EMAIL, accountID: ESH_ACCOUNT_ID});
await Onyx.set(ONYXKEYS.PERSONAL_DETAILS_LIST, {
[ESH_ACCOUNT_ID]: {accountID: ESH_ACCOUNT_ID, login: ESH_EMAIL, localCurrencyCode: CONST.CURRENCY.EUR},
});
await waitForBatchedUpdates();

const policyID = Policy.generatePolicyID();
// Pass explicit GBP currency — this should win over the session user's EUR localCurrencyCode
Policy.createDraftWorkspace({
introSelected: {choice: CONST.ONBOARDING_CHOICES.MANAGE_TEAM},
workspaceName: WORKSPACE_NAME,
currentUserAccountID: ESH_ACCOUNT_ID,
currentUserEmail: ESH_EMAIL,
policyOwnerEmail: ESH_EMAIL,
policyID,
currency: 'GBP',
});
await waitForBatchedUpdates();

const draft = await getOnyxValue(`${ONYXKEYS.COLLECTION.POLICY_DRAFTS}${policyID}`);

expect(draft?.outputCurrency).toBe('GBP');
expect(draft?.outputCurrency).not.toBe(CONST.CURRENCY.EUR);
});
});

describe('upgradeToCorporate', () => {
Expand Down
Loading
Loading