Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[OldDot Rules Migration] Expense report rules #47468

Merged
Merged
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
3081420
Add ExpenseReportRulesSection
WojtekBoman Aug 8, 2024
3623d4a
menu setup
BrtqKr Aug 12, 2024
3e622bf
replace items with ToggleSettingOptionRow
BrtqKr Aug 12, 2024
e99bf88
add custom report names section content wip
BrtqKr Aug 12, 2024
bff54c3
add translations
BrtqKr Aug 12, 2024
94a0db2
setup rhp nav
BrtqKr Aug 12, 2024
b07708a
add bullet points, wire up form wip
BrtqKr Aug 13, 2024
2e82822
wire up custom name form
BrtqKr Aug 13, 2024
0d6aa6f
cleanup custom names, prevent from changing names wip
BrtqKr Aug 13, 2024
4d15101
cleanup custom names
BrtqKr Aug 13, 2024
66382f0
wire up prevent member created title
BrtqKr Aug 13, 2024
6be513d
wire up prevent self approval
BrtqKr Aug 13, 2024
2169b17
add remaining routes
BrtqKr Aug 14, 2024
132ccbb
auto approve reports under amount page wip
BrtqKr Aug 14, 2024
285cf5e
wire up auto approval
BrtqKr Aug 14, 2024
5797fb1
add percentage form
BrtqKr Aug 14, 2024
2e75abd
wire up auto approval audit rate
BrtqKr Aug 14, 2024
45b46b4
wire up auto pay
BrtqKr Aug 14, 2024
72c38a4
rule lock conditions wip
BrtqKr Aug 14, 2024
6f59541
wire up enablePolicyAutoReimbursementLimit
BrtqKr Aug 19, 2024
daa7c9c
wire up enablePolicyAutoReimbursementLimit, validate wip
BrtqKr Aug 19, 2024
b188339
wire up enableAutoApprovalOptions
BrtqKr Aug 19, 2024
36160d3
wire up auto approve reports under
BrtqKr Aug 19, 2024
7e72524
wire up random report audit
BrtqKr Aug 20, 2024
21549c6
wire up enable custom report names
BrtqKr Aug 20, 2024
8c8f270
wire up custom report name
BrtqKr Aug 20, 2024
269dedd
wire up custom report names
BrtqKr Aug 20, 2024
34a5c4b
wire up prevent self approval
BrtqKr Aug 20, 2024
9bc374a
add fallback subtitle, fix translations
BrtqKr Aug 20, 2024
b881703
add custom name validation
BrtqKr Aug 20, 2024
215a252
add validation, fix amount form validation
BrtqKr Aug 20, 2024
b1df169
add fallbacks
BrtqKr Aug 20, 2024
b5c7486
add side effects
BrtqKr Aug 20, 2024
0edff08
cleanup jsdoc
BrtqKr Aug 20, 2024
edc14fe
move actions to policy
BrtqKr Aug 20, 2024
67e9e83
Merge remote-tracking branch 'origin/main' into brtqkr/expense-report…
BrtqKr Aug 20, 2024
b89de0a
fix audit rate command
BrtqKr Aug 20, 2024
00b8175
add keys
BrtqKr Aug 20, 2024
05f9529
cleanup
BrtqKr Aug 21, 2024
34eb99a
review fixes
BrtqKr Aug 21, 2024
2af9b37
fix translations
BrtqKr Aug 21, 2024
d23fb35
add jsdoc
BrtqKr Aug 21, 2024
1f327fa
Merge remote-tracking branch 'origin/main' into brtqkr/expense-report…
BrtqKr Aug 23, 2024
7b73789
fix command
BrtqKr Aug 23, 2024
db3f8c7
add pending fields
BrtqKr Aug 23, 2024
4b044a0
Merge remote-tracking branch 'origin/main' into brtqkr/expense-report…
BrtqKr Aug 23, 2024
1ef024a
fix types
BrtqKr Aug 23, 2024
ea72e31
review fixes
BrtqKr Aug 26, 2024
6d06f5d
cleanup
BrtqKr Aug 26, 2024
7b8a235
cleanup
BrtqKr Aug 26, 2024
058773f
Merge remote-tracking branch 'origin/main' into brtqkr/expense-report…
BrtqKr Aug 28, 2024
6bcb2e4
cleanup
BrtqKr Aug 28, 2024
9fc1685
cleanup
BrtqKr Aug 28, 2024
79c5ae6
cleanup
BrtqKr Aug 28, 2024
c48575b
add offline with feedback
BrtqKr Aug 29, 2024
a22d5fb
add fallback values
BrtqKr Aug 29, 2024
db46fb0
cleanup
BrtqKr Aug 29, 2024
b9eb9ae
lint fix
BrtqKr Aug 29, 2024
721a0ec
Merge remote-tracking branch 'origin/main' into brtqkr/expense-report…
BrtqKr Sep 2, 2024
b229a26
remove wrapper
BrtqKr Sep 2, 2024
816deeb
make pending fields more direct
BrtqKr Sep 2, 2024
001041f
change permissions
BrtqKr Sep 2, 2024
927461f
block access when unavailable
BrtqKr Sep 2, 2024
8a46e91
cleanup
BrtqKr Sep 2, 2024
6cd2540
remove tmp permissions
BrtqKr Sep 2, 2024
ed21e12
modify pending fields
BrtqKr Sep 2, 2024
550939e
block api calls when the value is identical
BrtqKr Sep 2, 2024
5d81f1b
add fallback
BrtqKr Sep 2, 2024
1a008ba
add fallbacks
BrtqKr Sep 2, 2024
e7fdedf
move conditions higher
BrtqKr Sep 2, 2024
e921c73
policyID fallback changes, move conditon to utils function
BrtqKr Sep 2, 2024
3f0b321
cleanup
BrtqKr Sep 2, 2024
ab1a8cb
cleanup
BrtqKr Sep 2, 2024
020b1e3
reivew changes
BrtqKr Sep 3, 2024
c71279f
add conditional pending actions
BrtqKr Sep 3, 2024
efe9fe6
change error message
BrtqKr Sep 4, 2024
2d55ee0
Merge remote-tracking branch 'origin/main' into brtqkr/expense-report…
BrtqKr Sep 5, 2024
0ef8fb2
swap condition for workflow approvals unavailable
BrtqKr Sep 5, 2024
3f55bd3
run prettier
BrtqKr Sep 5, 2024
442d734
update translations
BrtqKr Sep 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions assets/images/feed.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions assets/images/simple-illustrations/simple-illustration__rules.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1188,6 +1188,7 @@ const CONST = {
VISIBLE_PASSWORD: 'visible-password',
ASCII_CAPABLE: 'ascii-capable',
NUMBER_PAD: 'number-pad',
DECIMAL_PAD: 'decimal-pad',
},

INPUT_MODE: {
Expand Down Expand Up @@ -2025,11 +2026,16 @@ const CONST = {
// Often referred to as "collect" workspaces
TEAM: 'team',
},
FIELD_LIST_TITLE_FIELD_ID: 'text_title',
DEFAULT_REPORT_NAME_PATTERN: '{report:type} {report:startdate}',
marcaaron marked this conversation as resolved.
Show resolved Hide resolved
ROLE: {
ADMIN: 'admin',
AUDITOR: 'auditor',
USER: 'user',
},
AUTO_REIMBURSEMENT_MAX_LIMIT_CENTS: 2000000,
AUTO_REIMBURSEMENT_DEFAULT_LIMIT_CENTS: 10000,

AUTO_REPORTING_FREQUENCIES: {
INSTANT: 'instant',
IMMEDIATE: 'immediate',
Expand Down Expand Up @@ -2082,6 +2088,7 @@ const CONST = {
ARE_EXPENSIFY_CARDS_ENABLED: 'areExpensifyCardsEnabled',
ARE_INVOICES_ENABLED: 'areInvoicesEnabled',
ARE_TAXES_ENABLED: 'tax',
ARE_RULES_ENABLED: 'areRulesEnabled',
},
DEFAULT_CATEGORIES: [
'Advertising',
Expand Down Expand Up @@ -5471,6 +5478,14 @@ const CONST = {
description: 'workspace.upgrade.taxCodes.description' as const,
icon: 'Coins',
},
rules: {
id: 'rules' as const,
alias: 'rules',
name: 'Rules',
title: 'workspace.upgrade.rules.title' as const,
description: 'workspace.upgrade.rules.description' as const,
icon: 'Rules',
},
};
},
REPORT_FIELD_TYPES: {
Expand Down
12 changes: 12 additions & 0 deletions src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,14 @@ const ONYXKEYS = {
SEARCH_ADVANCED_FILTERS_FORM_DRAFT: 'searchAdvancedFiltersFormDraft',
TEXT_PICKER_MODAL_FORM: 'textPickerModalForm',
TEXT_PICKER_MODAL_FORM_DRAFT: 'textPickerModalFormDraft',
RULES_CUSTOM_NAME_MODAL_FORM: 'rulesCustomNameModalForm',
RULES_CUSTOM_NAME_MODAL_FORM_DRAFT: 'rulesCustomNameModalFormDraft',
RULES_AUTO_APPROVE_REPORTS_UNDER_MODAL_FORM: 'rulesAutoApproveReportsUnderModalForm',
RULES_AUTO_APPROVE_REPORTS_UNDER_MODAL_FORM_DRAFT: 'rulesAutoApproveReportsUnderModalFormDraft',
RULES_RANDOM_REPORT_AUDIT_MODAL_FORM: 'rulesRandomReportAuditModalForm',
RULES_RANDOM_REPORT_AUDIT_MODAL_FORM_DRAFT: 'rulesRandomReportAuditModalFormDraft',
RULES_AUTO_PAY_REPORTS_UNDER_MODAL_FORM: 'rulesAutoPayReportsUnderModalForm',
RULES_AUTO_PAY_REPORTS_UNDER_MODAL_FORM_DRAFT: 'rulesAutoPayReportsUnderModalFormDraft',
},
} as const;

Expand Down Expand Up @@ -702,6 +710,10 @@ type OnyxFormValuesMapping = {
[ONYXKEYS.FORMS.SAGE_INTACCT_DIMENSION_TYPE_FORM]: FormTypes.SageIntacctDimensionForm;
[ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM]: FormTypes.SearchAdvancedFiltersForm;
[ONYXKEYS.FORMS.TEXT_PICKER_MODAL_FORM]: FormTypes.TextPickerModalForm;
[ONYXKEYS.FORMS.RULES_CUSTOM_NAME_MODAL_FORM]: FormTypes.RulesCustomNameModalForm;
[ONYXKEYS.FORMS.RULES_AUTO_APPROVE_REPORTS_UNDER_MODAL_FORM]: FormTypes.RulesAutoApproveReportsUnderModalForm;
[ONYXKEYS.FORMS.RULES_RANDOM_REPORT_AUDIT_MODAL_FORM]: FormTypes.RulesRandomReportAuditModalForm;
[ONYXKEYS.FORMS.RULES_AUTO_PAY_REPORTS_UNDER_MODAL_FORM]: FormTypes.RulesAutoPayReportsUnderModalForm;
};

type OnyxFormDraftValuesMapping = {
Expand Down
20 changes: 20 additions & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -927,6 +927,10 @@ const ROUTES = {
route: 'settings/workspaces/:policyID/expensify-card/settings/frequency',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/expensify-card/settings/frequency` as const,
},
WORKSPACE_RULES: {
route: 'settings/workspaces/:policyID/rules',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/rules` as const,
},
WORKSPACE_DISTANCE_RATES: {
route: 'settings/workspaces/:policyID/distance-rates',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/distance-rates` as const,
Expand Down Expand Up @@ -955,6 +959,22 @@ const ROUTES = {
route: 'settings/workspaces/:policyID/distance-rates/:rateID/tax-rate/edit',
getRoute: (policyID: string, rateID: string) => `settings/workspaces/${policyID}/distance-rates/${rateID}/tax-rate/edit` as const,
},
RULES_CUSTOM_NAME: {
route: 'settings/workspaces/:policyID/rules/name',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/rules/name` as const,
},
RULES_AUTO_APPROVE_REPORTS_UNDER: {
route: 'settings/workspaces/:policyID/rules/auto-approve',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/rules/auto-approve` as const,
},
RULES_RANDOM_REPORT_AUDIT: {
route: 'settings/workspaces/:policyID/rules/audit',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/rules/audit` as const,
},
RULES_AUTO_PAY_REPORTS_UNDER: {
route: 'settings/workspaces/:policyID/rules/auto-pay',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/rules/auto-pay` as const,
},
// Referral program promotion
REFERRAL_DETAILS_MODAL: {
route: 'referral/:contentType',
Expand Down
5 changes: 5 additions & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,11 @@ const SCREENS = {
DISTANCE_RATE_TAX_RECLAIMABLE_ON_EDIT: 'Distance_Rate_Tax_Reclaimable_On_Edit',
DISTANCE_RATE_TAX_RATE_EDIT: 'Distance_Rate_Tax_Rate_Edit',
UPGRADE: 'Workspace_Upgrade',
RULES: 'Policy_Rules',
RULES_CUSTOM_NAME: 'Rules_Custom_Name',
RULES_AUTO_APPROVE_REPORTS_UNDER: 'Rules_Auto_Approve_Reports_Under',
RULES_RANDOM_REPORT_AUDIT: 'Rules_Random_Report_Audit',
RULES_AUTO_PAY_REPORTS_UNDER: 'Rules_AutoPay_Reports_Under',
},

EDIT_REQUEST: {
Expand Down
56 changes: 52 additions & 4 deletions src/components/AmountForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import * as MoneyRequestUtils from '@libs/MoneyRequestUtils';
import CONST from '@src/CONST';
import BigNumberPad from './BigNumberPad';
import FormHelpMessage from './FormHelpMessage';
import TextInput from './TextInput';
import isTextInputFocused from './TextInput/BaseTextInput/isTextInputFocused';
import type {BaseTextInputProps, BaseTextInputRef} from './TextInput/BaseTextInput/types';
import TextInputWithCurrencySymbol from './TextInputWithCurrencySymbol';
Expand Down Expand Up @@ -41,8 +42,12 @@ type AmountFormProps = {

/** Custom max amount length. It defaults to CONST.IOU.AMOUNT_MAX_LENGTH */
amountMaxLength?: number;

label?: string;

displayAsTextInput?: boolean;
} & Pick<TextInputWithCurrencySymbolProps, 'hideCurrencySymbol' | 'extraSymbol'> &
Pick<BaseTextInputProps, 'autoFocus'>;
Pick<BaseTextInputProps, 'autoFocus' | 'hasError'>;

/**
* Returns the new selection object based on the updated amount's length
Expand All @@ -57,7 +62,18 @@ const NUM_PAD_CONTAINER_VIEW_ID = 'numPadContainerView';
const NUM_PAD_VIEW_ID = 'numPadView';

function AmountForm(
{value: amount, currency = CONST.CURRENCY.USD, extraDecimals = 0, amountMaxLength, errorText, onInputChange, onCurrencyButtonPress, isCurrencyPressable = true, ...rest}: AmountFormProps,
{
value: amount,
currency = CONST.CURRENCY.USD,
extraDecimals = 0,
amountMaxLength,
onInputChange,
onCurrencyButtonPress,
displayAsTextInput = false,
isCurrencyPressable = true,
label,
...rest
}: AmountFormProps,
forwardedRef: ForwardedRef<BaseTextInputRef>,
) {
const styles = useThemeStyles();
Expand Down Expand Up @@ -195,6 +211,38 @@ function AmountForm(
const formattedAmount = MoneyRequestUtils.replaceAllDigits(currentAmount, toLocaleDigit);
const canUseTouchScreen = DeviceCapabilities.canUseTouchScreen();

if (displayAsTextInput) {
return (
<TextInput
label={label}
value={formattedAmount}
onChangeText={setNewAmount}
placeholder={numberFormat(0)}
ref={(ref: BaseTextInputRef) => {
if (typeof forwardedRef === 'function') {
forwardedRef(ref);
} else if (forwardedRef && 'current' in forwardedRef) {
// eslint-disable-next-line no-param-reassign
forwardedRef.current = ref;
}
textInput.current = ref;
}}
selection={selection}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BrtqKr Please help to explain why we need to change this file

Copy link
Contributor Author

@BrtqKr BrtqKr Aug 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I might have been missing something from the textinput version, but I might have fixed it while doing other things. It's probably no longer necessary

onSelectionChange={(e: NativeSyntheticEvent<TextInputSelectionChangeEventData>) => {
if (!shouldUpdateSelection) {
return;
}
setSelection(e.nativeEvent.selection);
}}
prefixCharacter={currency}
prefixStyle={styles.colorMuted}
keyboardType={CONST.KEYBOARD_TYPE.DECIMAL_PAD}
// eslint-disable-next-line react/jsx-props-no-spreading
{...rest}
/>
);
}

return (
<>
<View
Expand Down Expand Up @@ -231,11 +279,11 @@ function AmountForm(
// eslint-disable-next-line react/jsx-props-no-spreading
{...rest}
/>
{!!errorText && (
{!!rest.errorText && (
<FormHelpMessage
style={[styles.pAbsolute, styles.b0, canUseTouchScreen ? styles.mb0 : styles.mb3, styles.ph5, styles.w100]}
isError
message={errorText}
message={rest.errorText}
Comment on lines -299 to +304
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this, on the other hand, was necessary, because the error handling was broken in general

/>
)}
</View>
Expand Down
52 changes: 52 additions & 0 deletions src/components/BulletList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import type {ReactNode} from 'react';
import React from 'react';
import {View} from 'react-native';
import useThemeStyles from '@hooks/useThemeStyles';
import Text from './Text';

type BulletListItem = string;

type BulletListProps = {
/** List of items for the list. Eeach item will be rendered as a sepearte point. */
marcaaron marked this conversation as resolved.
Show resolved Hide resolved
items: BulletListItem[];

/** Header section of the list */
header: string | ReactNode;
};

function BulletList({items, header}: BulletListProps) {
const styles = useThemeStyles();

const baseTextStyles = [styles.mutedNormalTextLabel];

const renderBulletListHeader = () => {
if (typeof header === 'string') {
return <Text style={baseTextStyles}>{header}</Text>;
}
return header;
};

const renderBulletPoint = (item: string) => {
return (
<Text
style={baseTextStyles}
key={item}
>
<Text style={[styles.ph2, baseTextStyles]}>•</Text>
{item}
</Text>
);
};

return (
<View style={[styles.w100, styles.mt2]}>
{renderBulletListHeader()}
<View>{items.map((item) => renderBulletPoint(item))}</View>
</View>
);
}

BulletList.displayName = 'BulletList';

export type {BulletListProps};
export default BulletList;
2 changes: 2 additions & 0 deletions src/components/Form/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type CountrySelector from '@components/CountrySelector';
import type CurrencySelector from '@components/CurrencySelector';
import type DatePicker from '@components/DatePicker';
import type EmojiPickerButtonDropdown from '@components/EmojiPicker/EmojiPickerButtonDropdown';
import type PercentageForm from '@components/PercentageForm';
import type Picker from '@components/Picker';
import type RadioButtons from '@components/RadioButtons';
import type RoomNameInput from '@components/RoomNameInput';
Expand Down Expand Up @@ -42,6 +43,7 @@ type ValidInputs =
| typeof CountrySelector
| typeof CurrencySelector
| typeof AmountForm
| typeof PercentageForm
| typeof BusinessTypePicker
| typeof DimensionTypeSelector
| typeof StateSelector
Expand Down
2 changes: 2 additions & 0 deletions src/components/Icon/Expensicons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ import ExpensifyLogoNew from '@assets/images/expensify-logo-new.svg';
import ExpensifyWordmark from '@assets/images/expensify-wordmark.svg';
import EyeDisabled from '@assets/images/eye-disabled.svg';
import Eye from '@assets/images/eye.svg';
import Feed from '@assets/images/feed.svg';
import Filter from '@assets/images/filter.svg';
import Filters from '@assets/images/filters.svg';
import Flag from '@assets/images/flag.svg';
Expand Down Expand Up @@ -386,4 +387,5 @@ export {
Filters,
CalendarSolid,
Filter,
Feed,
};
2 changes: 2 additions & 0 deletions src/components/Icon/Illustrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ import ReceiptEnvelope from '@assets/images/simple-illustrations/simple-illustra
import ReceiptLocationMarker from '@assets/images/simple-illustrations/simple-illustration__receipt-location-marker.svg';
import ReceiptWrangler from '@assets/images/simple-illustrations/simple-illustration__receipt-wrangler.svg';
import ReceiptUpload from '@assets/images/simple-illustrations/simple-illustration__receiptupload.svg';
import Rules from '@assets/images/simple-illustrations/simple-illustration__rules.svg';
import SanFrancisco from '@assets/images/simple-illustrations/simple-illustration__sanfrancisco.svg';
import SendMoney from '@assets/images/simple-illustrations/simple-illustration__sendmoney.svg';
import ShieldYellow from '@assets/images/simple-illustrations/simple-illustration__shield.svg';
Expand Down Expand Up @@ -216,4 +217,5 @@ export {
Tire,
BigVault,
Filters,
Rules,
};
2 changes: 1 addition & 1 deletion src/components/MenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,7 @@ function MenuItem(
)}
</View>
)}
{titleComponent}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also please help to explain this change. Note that, this component is used in many places in our app

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to use titleComponent to achieve a different styling and realized that it is not working with the variant I was planning to use. I'll remove it to avoid regressions from this PR and push it separately.

{!!description && !shouldShowDescriptionOnTop && (
<Text
style={descriptionTextStyles}
Expand Down Expand Up @@ -738,7 +739,6 @@ function MenuItem(
</View>
)}
{!!furtherDetailsComponent && <View style={[styles.flexRow, styles.alignItemsCenter]}>{furtherDetailsComponent}</View>}
{titleComponent}
</View>
</View>
</View>
Expand Down
Loading
Loading