Skip to content

Commit

Permalink
Merge pull request #40840 from allroundexperts/feat-40668
Browse files Browse the repository at this point in the history
Update logic for categorising expenses
  • Loading branch information
thienlnam authored Apr 25, 2024
2 parents 4c03f95 + 9fce2e8 commit 1abbf42
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 80 deletions.
21 changes: 21 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1619,6 +1619,27 @@ const CONST = {
DISABLE: 'disable',
ENABLE: 'enable',
},
DEFAULT_CATEGORIES: [
'Advertising',
'Benefits',
'Car',
'Equipment',
'Fees',
'Home Office',
'Insurance',
'Interest',
'Labor',
'Maintenance',
'Materials',
'Meals and Entertainment',
'Office Supplies',
'Other',
'Professional Services',
'Rent',
'Taxes',
'Travel',
'Utilities',
],
OWNERSHIP_ERRORS: {
NO_BILLING_CARD: 'noBillingCard',
AMOUNT_OWED: 'amountOwed',
Expand Down
30 changes: 29 additions & 1 deletion src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import type {EmptyObject} from '@src/types/utils/EmptyObject';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import type IconAsset from '@src/types/utils/IconAsset';
import * as IOU from './actions/IOU';
import * as PolicyActions from './actions/Policy';
import * as store from './actions/ReimbursementAccount/store';
import * as CurrencyUtils from './CurrencyUtils';
import DateUtils from './DateUtils';
Expand Down Expand Up @@ -6116,7 +6117,34 @@ function createDraftTransactionAndNavigateToParticipantSelector(transactionID: s
mccGroup,
} as Transaction);

Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(CONST.IOU.TYPE.SUBMIT, transactionID, reportID, undefined, actionName));
const filteredPolicies = Object.values(allPolicies ?? {}).filter(
(policy) => policy?.type !== CONST.POLICY.TYPE.PERSONAL && policy?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE,
);

if (actionName === CONST.IOU.ACTION.SUBMIT || (allPolicies && filteredPolicies.length > 0)) {
Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(CONST.IOU.TYPE.SUBMIT, transactionID, reportID, undefined, actionName));
return;
}

const {expenseChatReportID, policyID, policyName} = PolicyActions.createWorkspace();
const isCategorizing = actionName === CONST.IOU.ACTION.CATEGORIZE;

IOU.setMoneyRequestParticipants(transactionID, [
{
selected: true,
accountID: 0,
isPolicyExpenseChat: true,
reportID: expenseChatReportID,
policyID,
searchText: policyName,
},
]);
const iouConfirmationPageRoute = ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, expenseChatReportID);
if (isCategorizing) {
Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute(actionName, CONST.IOU.TYPE.SUBMIT, transactionID, expenseChatReportID, iouConfirmationPageRoute));
} else {
Navigation.navigate(iouConfirmationPageRoute);
}
}

/**
Expand Down
122 changes: 80 additions & 42 deletions src/libs/actions/Policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2075,6 +2075,69 @@ function createDraftInitialWorkspace(policyOwnerEmail = '', policyName = '', pol
Onyx.update(optimisticData);
}

function buildOptimisticPolicyCategories(policyID: string, categories: readonly string[]) {
const optimisticCategoryMap = categories.reduce(
(acc, category) => ({
...acc,
[category]: {
name: category,
enabled: true,
errors: null,
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
},
}),
{},
);

const successCategoryMap = categories.reduce(
(acc, category) => ({
...acc,
[category]: {
errors: null,
pendingAction: null,
},
}),
{},
);

const failureCategoryMap = categories.reduce(
(acc, category) => ({
...acc,
[category]: {
errors: ErrorUtils.getMicroSecondOnyxError('workspace.categories.createFailureMessage'),
pendingAction: null,
},
}),
{},
);

const onyxData: OnyxData = {
optimisticData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`,
value: optimisticCategoryMap,
},
],
successData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`,
value: successCategoryMap,
},
],
failureData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`,
value: failureCategoryMap,
},
],
};

return onyxData;
}

/**
* Optimistically creates a new workspace and default workspace chats
*
Expand All @@ -2083,7 +2146,7 @@ function createDraftInitialWorkspace(policyOwnerEmail = '', policyName = '', pol
* @param [policyName] custom policy name we will use for created workspace
* @param [policyID] custom policy id we will use for created workspace
*/
function createWorkspace(policyOwnerEmail = '', makeMeAdmin = false, policyName = '', policyID = generatePolicyID()): string {
function createWorkspace(policyOwnerEmail = '', makeMeAdmin = false, policyName = '', policyID = generatePolicyID()): CreateWorkspaceParams {
const workspaceName = policyName || generateDefaultWorkspaceName(policyOwnerEmail);

const {customUnits, customUnitID, customUnitRateID, outputCurrency} = buildOptimisticCustomUnits();
Expand All @@ -2103,6 +2166,8 @@ function createWorkspace(policyOwnerEmail = '', makeMeAdmin = false, policyName
expenseCreatedReportActionID,
} = ReportUtils.buildOptimisticWorkspaceChats(policyID, workspaceName);

const optimisticCategoriesData = buildOptimisticPolicyCategories(policyID, CONST.POLICY.DEFAULT_CATEGORIES);

const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.SET,
Expand Down Expand Up @@ -2293,6 +2358,18 @@ function createWorkspace(policyOwnerEmail = '', makeMeAdmin = false, policyName
},
];

if (optimisticCategoriesData.optimisticData) {
optimisticData.push(...optimisticCategoriesData.optimisticData);
}

if (optimisticCategoriesData.failureData) {
failureData.push(...optimisticCategoriesData.failureData);
}

if (optimisticCategoriesData.successData) {
successData.push(...optimisticCategoriesData.successData);
}

const params: CreateWorkspaceParams = {
policyID,
announceChatReportID,
Expand All @@ -2311,7 +2388,7 @@ function createWorkspace(policyOwnerEmail = '', makeMeAdmin = false, policyName

API.write(WRITE_COMMANDS.CREATE_WORKSPACE, params, {optimisticData, successData, failureData});

return adminsChatReportID;
return params;
}

function openWorkspaceReimburseView(policyID: string) {
Expand Down Expand Up @@ -3085,46 +3162,7 @@ function setWorkspaceCategoryEnabled(policyID: string, categoriesToUpdate: Recor
}

function createPolicyCategory(policyID: string, categoryName: string) {
const onyxData: OnyxData = {
optimisticData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`,
value: {
[categoryName]: {
name: categoryName,
enabled: true,
errors: null,
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
},
},
},
],
successData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`,
value: {
[categoryName]: {
errors: null,
pendingAction: null,
},
},
},
],
failureData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`,
value: {
[categoryName]: {
errors: ErrorUtils.getMicroSecondOnyxError('workspace.categories.createFailureMessage'),
pendingAction: null,
},
},
},
],
};
const onyxData = buildOptimisticPolicyCategories(policyID, [categoryName]);

const parameters = {
policyID,
Expand Down
2 changes: 1 addition & 1 deletion src/pages/OnboardingWork/BaseOnboardingWork.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ function BaseOnboardingWork({currentUserPersonalDetails, shouldUseNativeStyles,

const work = values.work.trim();

const adminsChatReportID = Policy.createWorkspace(undefined, true, work);
const {adminsChatReportID} = Policy.createWorkspace(undefined, true, work);

Report.completeOnboarding(
onboardingPurposeSelected,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import lodashEvery from 'lodash/every';
import lodashGet from 'lodash/get';
import lodashIsEqual from 'lodash/isEqual';
import lodashMap from 'lodash/map';
Expand All @@ -9,11 +8,8 @@ import lodashValues from 'lodash/values';
import PropTypes from 'prop-types';
import React, {memo, useCallback, useEffect, useMemo} from 'react';
import {useOnyx} from 'react-native-onyx';
import BlockingView from '@components/BlockingViews/BlockingView';
import Button from '@components/Button';
import FormHelpMessage from '@components/FormHelpMessage';
import * as Illustrations from '@components/Icon/Illustrations';
import OfflineIndicator from '@components/OfflineIndicator';
import {usePersonalDetails} from '@components/OnyxProvider';
import {useOptionsList} from '@components/OptionListContextProvider';
import ReferralProgramCTA from '@components/ReferralProgramCTA';
Expand All @@ -26,15 +22,11 @@ import useNetwork from '@hooks/useNetwork';
import usePermissions from '@hooks/usePermissions';
import useScreenWrapperTranstionStatus from '@hooks/useScreenWrapperTransitionStatus';
import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import Navigation from '@libs/Navigation/Navigation';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import variables from '@styles/variables';
import * as Report from '@userActions/Report';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';

const propTypes = {
/** Callback to request parent modal to go to next step, which should be split */
Expand Down Expand Up @@ -87,7 +79,6 @@ function MoneyTemporaryForRefactorRequestParticipantsSelector({participants, onF
const offlineMessage = isOffline ? [`${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}`, {isTranslated: true}] : '';

const maxParticipantsReached = participants.length === CONST.REPORT.MAXIMUM_PARTICIPANTS;
const {isSmallScreenWidth} = useWindowDimensions();

const isIOUSplit = iouType === CONST.IOU.TYPE.SPLIT;
const isCategorizeOrShareAction = [CONST.IOU.ACTION.CATEGORIZE, CONST.IOU.ACTION.SHARE].includes(action);
Expand Down Expand Up @@ -335,31 +326,6 @@ function MoneyTemporaryForRefactorRequestParticipantsSelector({participants, onF
);
}, [handleConfirmSelection, participants.length, isDismissed, referralContentType, shouldShowSplitBillErrorMessage, styles, translate]);

const renderEmptyWorkspaceView = () => (
<>
<BlockingView
icon={Illustrations.TeleScope}
iconWidth={variables.emptyWorkspaceIconWidth}
iconHeight={variables.emptyWorkspaceIconHeight}
title={translate('workspace.emptyWorkspace.notFound')}
shouldShowLink={false}
/>
<Button
success
large
text={translate('footer.learnMore')}
onPress={() => Navigation.navigate(ROUTES.SETTINGS_WORKSPACES)}
style={[styles.mh5, styles.mb5]}
/>
{isSmallScreenWidth && <OfflineIndicator />}
</>
);

const isAllSectionsEmpty = lodashEvery(sections, (section) => section.data.length === 0);
if (isCategorizeOrShareAction && isAllSectionsEmpty && didScreenTransitionEnd && debouncedSearchTerm.trim() === '' && areOptionsInitialized) {
return renderEmptyWorkspaceView();
}

return (
<SelectionList
onConfirm={handleConfirmSelection}
Expand Down
4 changes: 2 additions & 2 deletions src/pages/iou/request/step/IOURequestStepConfirmation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,13 @@ function IOURequestStepConfirmation({
const requestType = TransactionUtils.getRequestType(transaction);

const headerTitle = useMemo(() => {
if (isSharingTrackExpense) {
if (isCategorizingTrackExpense) {
return translate('iou.categorize');
}
if (isSubmittingFromTrackExpense) {
return translate('iou.submitExpense');
}
if (isCategorizingTrackExpense) {
if (isSharingTrackExpense) {
return translate('iou.share');
}
if (iouType === CONST.IOU.TYPE.SPLIT) {
Expand Down

0 comments on commit 1abbf42

Please sign in to comment.