Skip to content

Commit

Permalink
Merge pull request Expensify#32528 from infinitered/cdanwards/violati…
Browse files Browse the repository at this point in the history
…ons/money-request-violations
  • Loading branch information
cead22 authored Jan 5, 2024
2 parents e3cb81c + 9b2fb39 commit 095161a
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 9 deletions.
87 changes: 83 additions & 4 deletions src/libs/actions/IOU.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import * as ReportUtils from '@libs/ReportUtils';
import * as TransactionUtils from '@libs/TransactionUtils';
import * as UserUtils from '@libs/UserUtils';
import ViolationsUtils from '@libs/ViolationsUtils';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
Expand Down Expand Up @@ -306,6 +307,27 @@ function getReceiptError(receipt, filename, isScanRequest = true) {
: ErrorUtils.getMicroSecondOnyxErrorObject({error: CONST.IOU.RECEIPT_ERROR, source: receipt.source, filename});
}

/**
* 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} isNewIOUReport
* @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} hasOutstandingChildRequest
* @returns {Array} - An array containing the optimistic data, success data, and failure data.
*/
function buildOnyxDataForMoneyRequest(
chatReport,
iouReport,
Expand All @@ -319,6 +341,9 @@ function buildOnyxDataForMoneyRequest(
optimisticPolicyRecentlyUsedTags,
isNewChatReport,
isNewIOUReport,
policy,
policyTags,
policyCategories,
hasOutstandingChildRequest = false,
) {
const isScanRequest = TransactionUtils.isScanRequest(transaction);
Expand Down Expand Up @@ -556,6 +581,22 @@ function buildOnyxDataForMoneyRequest(
},
];

// Policy won't be set for P2P cases for which we don't need to compute violations
if (!policy || !policy.id) {
return [optimisticData, successData, failureData];
}

const violationsOnyxData = ViolationsUtils.getViolationsOnyxData(transaction, [], policy.requiresTag, policyTags, policy.requiresCategory, policyCategories);

if (violationsOnyxData) {
optimisticData.push(violationsOnyxData);
failureData.push({
onyxMethod: Onyx.METHOD.SET,
key: `${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transaction.transactionID}`,
value: [],
});
}

return [optimisticData, successData, failureData];
}

Expand All @@ -577,6 +618,9 @@ function buildOnyxDataForMoneyRequest(
* @param {String} [category]
* @param {String} [tag]
* @param {Boolean} [billable]
* @param {Object} [policy]
* @param {Object} [policyTags]
* @param {Object} [policyCategories]
* @returns {Object} data
* @returns {String} data.payerEmail
* @returns {Object} data.iouReport
Expand Down Expand Up @@ -606,6 +650,9 @@ function getMoneyRequestInformation(
category = undefined,
tag = undefined,
billable = undefined,
policy = undefined,
policyTags = undefined,
policyCategories = undefined,
) {
const payerEmail = OptionsListUtils.addSMSDomainIfPhoneNumber(participant.login);
const payerAccountID = Number(participant.accountID);
Expand Down Expand Up @@ -639,7 +686,6 @@ function getMoneyRequestInformation(
let needsToBeManuallySubmitted = false;
let isFromPaidPolicy = false;
if (isPolicyExpenseChat) {
const policy = ReportUtils.getPolicy(chatReport.policyID);
isFromPaidPolicy = PolicyUtils.isPaidGroupPolicy(policy);

// If the scheduled submit is turned off on the policy, user needs to manually submit the report which is indicated by GBR in LHN
Expand Down Expand Up @@ -774,6 +820,9 @@ function getMoneyRequestInformation(
optimisticPolicyRecentlyUsedTags,
isNewChatReport,
isNewIOUReport,
policy,
policyTags,
policyCategories,
hasOutstandingChildRequest,
);

Expand Down Expand Up @@ -808,9 +857,12 @@ function getMoneyRequestInformation(
* @param {String} currency
* @param {String} merchant
* @param {Boolean} [billable]
* @param {Obejct} validWaypoints
* @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) {
function createDistanceRequest(report, participant, comment, created, category, tag, amount, currency, merchant, billable, validWaypoints, policy, policyTags, 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;
Expand All @@ -834,6 +886,9 @@ function createDistanceRequest(report, participant, comment, created, category,
category,
tag,
billable,
policy,
policyTags,
policyCategories,
);
API.write(
'CreateDistanceRequest',
Expand Down Expand Up @@ -1104,6 +1159,9 @@ function updateDistanceRequest(transactionID, transactionThreadReportID, transac
* @param {String} [taxCode]
* @param {Number} [taxAmount]
* @param {Boolean} [billable]
* @param {Object} [policy]
* @param {Object} [policyTags]
* @param {Object} [policyCategories]
*/
function requestMoney(
report,
Expand All @@ -1121,12 +1179,33 @@ function requestMoney(
taxCode = '',
taxAmount = 0,
billable = undefined,
policy = undefined,
policyTags = undefined,
policyCategories = undefined,
) {
// 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 {payerAccountID, payerEmail, iouReport, chatReport, transaction, iouAction, createdChatReportActionID, createdIOUReportActionID, reportPreviewAction, onyxData} =
getMoneyRequestInformation(currentChatReport, participant, comment, amount, currency, created, merchant, payeeAccountID, payeeEmail, receipt, undefined, category, tag, billable);
getMoneyRequestInformation(
currentChatReport,
participant,
comment,
amount,
currency,
created,
merchant,
payeeAccountID,
payeeEmail,
receipt,
undefined,
category,
tag,
billable,
policy,
policyTags,
policyCategories,
);
const activeReportID = isMoneyRequestReport ? report.reportID : chatReport.reportID;

API.write(
Expand Down
31 changes: 28 additions & 3 deletions src/pages/iou/request/step/IOURequestStepConfirmation.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import lodashGet from 'lodash/get';
import PropTypes from 'prop-types';
import React, {useCallback, useEffect, useMemo, useState} from 'react';
import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import categoryPropTypes from '@components/categoryPropTypes';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import * as Expensicons from '@components/Icon/Expensicons';
import MoneyRequestConfirmationList from '@components/MoneyTemporaryForRefactorRequestConfirmationList';
import ScreenWrapper from '@components/ScreenWrapper';
import tagPropTypes from '@components/tagPropTypes';
import transactionPropTypes from '@components/transactionPropTypes';
import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails';
import useLocalize from '@hooks/useLocalize';
Expand Down Expand Up @@ -46,6 +49,12 @@ const propTypes = {
/** The policy of the report */
...policyPropTypes,

/** The tag configuration of the report's policy */
policyTags: tagPropTypes,

/** The category configuration of the report's policy */
policyCategories: PropTypes.objectOf(categoryPropTypes),

/** The full IOU report */
report: reportPropTypes,

Expand All @@ -55,6 +64,8 @@ const propTypes = {
const defaultProps = {
personalDetails: {},
policy: {},
policyCategories: {},
policyTags: {},
report: {},
transaction: {},
...withCurrentUserPersonalDetailsDefaultProps,
Expand All @@ -63,6 +74,8 @@ function IOURequestStepConfirmation({
currentUserPersonalDetails,
personalDetails,
policy,
policyTags,
policyCategories,
report,
route: {
params: {iouType, reportID, transactionID},
Expand Down Expand Up @@ -164,9 +177,12 @@ function IOURequestStepConfirmation({
transactionTaxCode,
transactionTaxAmount,
transaction.billable,
policy,
policyTags,
policyCategories,
);
},
[report, transaction, transactionTaxCode, transactionTaxAmount, currentUserPersonalDetails.login, currentUserPersonalDetails.accountID],
[report, transaction, transactionTaxCode, transactionTaxAmount, currentUserPersonalDetails.login, currentUserPersonalDetails.accountID, policy, policyTags, policyCategories],
);

/**
Expand All @@ -187,9 +203,12 @@ function IOURequestStepConfirmation({
transaction.merchant,
transaction.billable,
TransactionUtils.getValidWaypoints(transaction.comment.waypoints, true),
policy,
policyTags,
policyCategories,
);
},
[report, transaction],
[policy, policyCategories, policyTags, report, transaction],
);

const createTransaction = useCallback(
Expand Down Expand Up @@ -375,7 +394,13 @@ export default compose(
// eslint-disable-next-line rulesdir/no-multiple-onyx-in-file
withOnyx({
policy: {
key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${lodashGet(report, 'policyID', '0')}`,
key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`,
},
policyCategories: {
key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report ? report.policyID : '0'}`,
},
policyTags: {
key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report ? report.policyID : '0'}`,
},
}),
)(IOURequestStepConfirmation);
44 changes: 42 additions & 2 deletions src/pages/iou/steps/MoneyRequestConfirmPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import categoryPropTypes from '@components/categoryPropTypes';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import * as Expensicons from '@components/Icon/Expensicons';
import MoneyRequestConfirmationList from '@components/MoneyRequestConfirmationList';
import {usePersonalDetails} from '@components/OnyxProvider';
import ScreenWrapper from '@components/ScreenWrapper';
import tagPropTypes from '@components/tagPropTypes';
import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails';
import withLocalize from '@components/withLocalize';
import useInitialValue from '@hooks/useInitialValue';
Expand All @@ -23,6 +25,7 @@ import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as ReportUtils from '@libs/ReportUtils';
import {iouDefaultProps, iouPropTypes} from '@pages/iou/propTypes';
import reportPropTypes from '@pages/reportPropTypes';
import {policyDefaultProps, policyPropTypes} from '@pages/workspace/withPolicy';
import * as IOU from '@userActions/IOU';
import * as Policy from '@userActions/Policy';
import CONST from '@src/CONST';
Expand All @@ -47,12 +50,22 @@ const propTypes = {
/** Holds data related to Money Request view state, rather than the underlying Money Request data. */
iou: iouPropTypes,

/** The policy of the current request */
policy: policyPropTypes,

policyTags: tagPropTypes,

policyCategories: PropTypes.objectOf(categoryPropTypes),

...withCurrentUserPersonalDetailsPropTypes,
};

const defaultProps = {
report: {},
policyCategories: {},
policyTags: {},
iou: iouDefaultProps,
policy: policyDefaultProps,
...withCurrentUserPersonalDetailsDefaultProps,
};

Expand Down Expand Up @@ -163,6 +176,9 @@ function MoneyRequestConfirmPage(props) {
props.iou.category,
props.iou.tag,
props.iou.billable,
props.policy,
props.policyTags,
props.policyCategories,
);
},
[
Expand All @@ -176,6 +192,9 @@ function MoneyRequestConfirmPage(props) {
props.iou.category,
props.iou.tag,
props.iou.billable,
props.policy,
props.policyTags,
props.policyCategories,
],
);

Expand All @@ -197,9 +216,25 @@ function MoneyRequestConfirmPage(props) {
props.iou.currency,
props.iou.merchant,
props.iou.billable,
props.policy,
props.policyTags,
props.policyCategories,
);
},
[props.report, props.iou.created, props.iou.transactionID, props.iou.category, props.iou.tag, props.iou.amount, props.iou.currency, props.iou.merchant, props.iou.billable],
[
props.report,
props.iou.created,
props.iou.transactionID,
props.iou.category,
props.iou.tag,
props.iou.amount,
props.iou.currency,
props.iou.merchant,
props.iou.billable,
props.policy,
props.policyTags,
props.policyCategories,
],
);

const createTransaction = useCallback(
Expand Down Expand Up @@ -424,10 +459,15 @@ export default compose(
key: `${ONYXKEYS.COLLECTION.SELECTED_TAB}${CONST.TAB.RECEIPT_TAB_ID}`,
},
}),
// eslint-disable-next-line rulesdir/no-multiple-onyx-in-file
withOnyx({
policy: {
key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`,
},
policyCategories: {
key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${report ? report.policyID : '0'}`,
},
policyTags: {
key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${report ? report.policyID : '0'}`,
},
}),
)(MoneyRequestConfirmPage);
12 changes: 12 additions & 0 deletions src/pages/workspace/withPolicy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,18 @@ const policyPropTypes = {
* }
*/
errorFields: PropTypes.objectOf(PropTypes.objectOf(PropTypes.string)),

/** Whether or not the policy requires tags */
requiresTag: PropTypes.bool,

/** Whether or not the policy requires categories */
requiresCategory: PropTypes.bool,

/** Whether or not the policy has multiple tag lists */
hasMultipleTagLists: PropTypes.bool,

/** Whether or not the policy has tax tracking enabled */
isTaxTrackingEnabled: PropTypes.bool,
}),

/** The employee list of this policy */
Expand Down

0 comments on commit 095161a

Please sign in to comment.