Skip to content

Commit 474a930

Browse files
committed
Merge branch 'main' of https://github.com/Expensify/App into fix/60633-global-vbba-followup
2 parents d0c7280 + bd59655 commit 474a930

File tree

135 files changed

+3075
-1164
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

135 files changed

+3075
-1164
lines changed

Mobile-Expensify

android/app/build.gradle

+2-2
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ android {
114114
minSdkVersion rootProject.ext.minSdkVersion
115115
targetSdkVersion rootProject.ext.targetSdkVersion
116116
multiDexEnabled rootProject.ext.multiDexEnabled
117-
versionCode 1009014100
118-
versionName "9.1.41-0"
117+
versionCode 1009014200
118+
versionName "9.1.42-0"
119119
// Supported language variants must be declared here to avoid from being removed during the compilation.
120120
// This also helps us to not include unnecessary language variants in the APK.
121121
resConfigs "en", "es"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
---
2+
title: Prohibited Expenses Rule
3+
description: Learn how to enable and use the Prohibited expenses rule to automatically flag receipts with restricted items such as alcohol, gambling, or tobacco.
4+
keywords: [prohibited expenses, receipt violation, SmartScan, alcohol, gambling, expense rules, workspace settings, line item compliance]
5+
---
6+
<div id="new-expensify" markdown="1">
7+
8+
Enable the **Prohibited expenses** rule to automatically flag receipts containing restricted purchases like alcohol, gambling, or tobacco. This rule uses Expensify’s AI-powered SmartScan to detect violations at the line-item level and notify admins for review.
9+
10+
# Prohibited Expense Rule
11+
12+
The Prohibited expenses rule allows Workspace Admins to enforce compliance by flagging receipts that contain restricted items. SmartScan analyzes individual line items and applies violations when prohibited categories are detected.
13+
14+
## How it works
15+
16+
Once enabled, this rule uses AI to review receipt line items during SmartScan. If a prohibited item is found, the expense is flagged for review.
17+
18+
- Available in both Expensify Classic and New Expensify.
19+
- Configuration is only available in New Expensify.
20+
- Automatically flags receipts for manual review by a Workspace Admin or approver.
21+
22+
## How to enable the rule
23+
24+
To turn on the Prohibited expenses rule:
25+
26+
1. Go to **Settings** > **Workspaces** > click _Workspace Name_ > **Rules** > **Expenses**.
27+
2. Scroll to the section titled **Prohibited expenses**.
28+
3. Toggle on the rule.
29+
4. Select the prohibited categories you want to monitor:
30+
- Adult entertainment
31+
- Alcohol
32+
- Gambling
33+
- Hotel incidentals
34+
- Tobacco
35+
36+
**Note:** This rule is disabled by default. Admins must enable it and choose which categories to apply.
37+
38+
## What happens when a prohibited item is detected?
39+
40+
If a SmartScan detects a prohibited item:
41+
42+
- A violation is added to the expense.
43+
- The expense displays the messages:
44+
- `"Receipt Issue Found"`
45+
- `"Prohibited expense: Alcohol"` (or the relevant flagged category).
46+
- The expense requires manual review by the approver.
47+
48+
---
49+
50+
# FAQ
51+
52+
## Who can enable the Prohibited Expenses Rule?
53+
54+
Only Workspace Admins can enable or adjust this rule in New Expensify.
55+
56+
## Will violations appear in Expensify Classic?
57+
58+
Yes. Even though configuration is handled in New Expensify, violations appear in both **Expensify Classic** and **New Expensify** when viewing expenses.
59+
60+
If the Domain Group setting, **Strictly enforce expense workspace rules** is enabled, it will block the submission of the expense with the prohibited item violation.
61+
62+
## Will SmartScan still work if the rule is off?
63+
64+
Yes. SmartScan will still extract the merchant, date, and amount. However, it will not flag line items for violations unless the rule is enabled.
65+
66+
## Is this rule part of SmartScan?
67+
68+
Yes. Once enabled, the rule works seamlessly with SmartScan to detect prohibited line items in all scanned receipts.
69+
70+
</div>

docs/articles/new-expensify/workspaces/Set-up-rules.md

+16
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,22 @@ Once Rules are enabled, you can customize individual expense settings:
3030
- **Billable default**: Set expenses as billable or non-billable by default.
3131
- **eReceipts**: Enable eReceipts for most USD credit transactions. This is available when the Default currency set in the Overview is set to USD.
3232

33+
# Configure Prohibited Expense Rule
34+
35+
To flag restricted expense types for manual review:
36+
37+
1. Go to **Settings** > **Workspaces** > click **Workspace Name** > **Rules** > **Expenses**.
38+
2. Scroll to the **Prohibited expenses** section.
39+
3. Toggle on the feature, then select the types of restricted items to flag:
40+
- Alcohol
41+
- Gambling
42+
- Tobacco
43+
- Hotel incidentals
44+
- Adult entertainment
45+
4. If an uploaded receipt contains any of the flagged items, the expense will be marked for manual review.
46+
47+
**Note:** Prohibited expense violations appear in both New Expensify and Expensify Classic. However, a Workspace Admin must enable the rules in **New Expensify** for them to take effect.
48+
3349
# Configure expense report rules
3450

3551
1. Click **Rules** in the left menu.

ios/NewExpensify/Info.plist

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
<key>CFBundlePackageType</key>
2424
<string>APPL</string>
2525
<key>CFBundleShortVersionString</key>
26-
<string>9.1.41</string>
26+
<string>9.1.42</string>
2727
<key>CFBundleSignature</key>
2828
<string>????</string>
2929
<key>CFBundleURLTypes</key>
@@ -44,7 +44,7 @@
4444
</dict>
4545
</array>
4646
<key>CFBundleVersion</key>
47-
<string>9.1.41.0</string>
47+
<string>9.1.42.0</string>
4848
<key>FullStory</key>
4949
<dict>
5050
<key>OrgId</key>

ios/NotificationServiceExtension/Info.plist

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
<key>CFBundleName</key>
1212
<string>$(PRODUCT_NAME)</string>
1313
<key>CFBundleShortVersionString</key>
14-
<string>9.1.41</string>
14+
<string>9.1.42</string>
1515
<key>CFBundleVersion</key>
16-
<string>9.1.41.0</string>
16+
<string>9.1.42.0</string>
1717
<key>NSExtension</key>
1818
<dict>
1919
<key>NSExtensionPointIdentifier</key>

ios/ShareViewController/Info.plist

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
<key>CFBundleName</key>
1212
<string>$(PRODUCT_NAME)</string>
1313
<key>CFBundleShortVersionString</key>
14-
<string>9.1.41</string>
14+
<string>9.1.42</string>
1515
<key>CFBundleVersion</key>
16-
<string>9.1.41.0</string>
16+
<string>9.1.42.0</string>
1717
<key>NSExtension</key>
1818
<dict>
1919
<key>NSExtensionAttributes</key>

package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "new.expensify",
3-
"version": "9.1.41-0",
3+
"version": "9.1.42-0",
44
"author": "Expensify, Inc.",
55
"homepage": "https://new.expensify.com",
66
"description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",

src/CONST.ts

+10
Original file line numberDiff line numberDiff line change
@@ -1103,6 +1103,7 @@ const CONST = {
11031103
PLAN_TYPES_AND_PRICING_HELP_URL: 'https://help.expensify.com/articles/new-expensify/billing-and-subscriptions/Plan-types-and-pricing',
11041104
MERGE_ACCOUNT_HELP_URL: 'https://help.expensify.com/articles/new-expensify/settings/Merge-Accounts',
11051105
CONNECT_A_BUSINESS_BANK_ACCOUNT_HELP_URL: 'https://help.expensify.com/articles/new-expensify/expenses-&-payments/Connect-a-Business-Bank-Account',
1106+
REGISTER_FOR_WEBINAR_URL: 'https://events.zoom.us/eo/Aif1I8qCi1GZ7KnLnd1vwGPmeukSRoPjFpyFAZ2udQWn0-B86e1Z~AggLXsr32QYFjq8BlYLZ5I06Dg',
11061107
TEST_RECEIPT_URL: `${CLOUDFRONT_URL}/images/fake-receipt__tacotodds.png`,
11071108
// Use Environment.getEnvironmentURL to get the complete URL with port number
11081109
DEV_NEW_EXPENSIFY_URL: 'https://dev.new.expensify.com:',
@@ -1995,6 +1996,7 @@ const CONST = {
19951996
HEIGHT: 416,
19961997
},
19971998
DESKTOP_HEADER_PADDING: 12,
1999+
SEARCH_ITEM_LIMIT: 15,
19982000
CATEGORY_SHORTCUT_BAR_HEIGHT: 32,
19992001
SMALL_EMOJI_PICKER_SIZE: {
20002002
WIDTH: '100%',
@@ -7004,6 +7006,9 @@ const CONST = {
70047006
SCAN_TEST_TOOLTIP: 'scanTestTooltip',
70057007
SCAN_TEST_TOOLTIP_MANAGER: 'scanTestTooltipManager',
70067008
SCAN_TEST_CONFIRMATION: 'scanTestConfirmation',
7009+
OUTSANDING_FILTER: 'outstandingFilter',
7010+
SETTINGS_TAB: 'settingsTab',
7011+
WORKSPACES_SETTINGS: 'workspacesSettings',
70077012
GBR_RBR_CHAT: 'chatGBRRBR',
70087013
ACCOUNT_SWITCHER: 'accountSwitcher',
70097014
EXPENSE_REPORTS_FILTER: 'expenseReportsFilter',
@@ -7057,6 +7062,11 @@ const CONST = {
70577062
EMBEDDED_DEMO_WHITELIST: ['http://', 'https://', 'about:'] as string[],
70587063
EMBEDDED_DEMO_IFRAME_TITLE: 'Test Drive',
70597064
},
7065+
7066+
ONBOARDING_HELP: {
7067+
TALK_TO_SALES: 'talkToSales',
7068+
REGISTER_FOR_WEBINAR: 'registerForWebinar',
7069+
},
70607070
} as const;
70617071

70627072
type Country = keyof typeof CONST.ALL_COUNTRIES;

src/ONYXKEYS.ts

+4
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,9 @@ const ONYXKEYS = {
501501
/** Information about loading states while talking with AI sales */
502502
TALK_TO_AI_SALES: 'talkToAISales',
503503

504+
/** Stores draft information while user is scheduling the call. */
505+
SCHEDULE_CALL_DRAFT: 'scheduleCallDraft',
506+
504507
/** Onyx updates that should be stored after sequential queue is flushed */
505508
QUEUE_FLUSHED_DATA: 'queueFlushedData',
506509

@@ -1154,6 +1157,7 @@ type OnyxValuesMapping = {
11541157
[ONYXKEYS.SHOULD_BILL_WHEN_DOWNGRADING]: boolean | undefined;
11551158
[ONYXKEYS.BILLING_RECEIPT_DETAILS]: OnyxTypes.BillingReceiptDetails;
11561159
[ONYXKEYS.NVP_SIDE_PANEL]: OnyxTypes.SidePanel;
1160+
[ONYXKEYS.SCHEDULE_CALL_DRAFT]: OnyxTypes.ScheduleCallDraft;
11571161
[ONYXKEYS.IS_FORCED_TO_CHANGE_CURRENCY]: boolean | undefined;
11581162
[ONYXKEYS.IS_COMING_FROM_GLOBAL_REIMBURSEMENTS_FLOW]: boolean | undefined;
11591163
};

src/ROUTES.ts

+8
Original file line numberDiff line numberDiff line change
@@ -2483,6 +2483,14 @@ const ROUTES = {
24832483
route: 'debug/transaction/:transactionID/violations/:index/json',
24842484
getRoute: (transactionID: string, index: string) => `debug/transaction/${transactionID}/violations/${index}/json` as const,
24852485
},
2486+
SCHEDULE_CALL_BOOK: {
2487+
route: 'r/:reportID/schedule-call/book',
2488+
getRoute: (reportID: string) => `r/${reportID}/schedule-call/book` as const,
2489+
},
2490+
SCHEDULE_CALL_CONFIRMATON: {
2491+
route: 'r/:reportID/schedule-call/confimation',
2492+
getRoute: (reportID: string) => `r/${reportID}/schedule-call/confimation` as const,
2493+
},
24862494
} as const;
24872495

24882496
/**

src/SCREENS.ts

+5
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ const SCREENS = {
215215
REPORT_EXPORT: 'Report_Export',
216216
MISSING_PERSONAL_DETAILS: 'MissingPersonalDetails',
217217
DEBUG: 'Debug',
218+
SCHEDULE_CALL: 'ScheduleCall',
218219
},
219220
PUBLIC_CONSOLE_DEBUG: 'Console_Debug',
220221
ONBOARDING_MODAL: {
@@ -717,6 +718,10 @@ const SCREENS = {
717718
TRANSACTION_VIOLATION_CREATE: 'Debug_Transaction_Violation_Create',
718719
TRANSACTION_VIOLATION: 'Debug_Transaction_Violation',
719720
},
721+
SCHEDULE_CALL: {
722+
BOOK: 'ScheduleCall_Book',
723+
CONFIRMATION: 'ScheduleCall_Confirmation',
724+
},
720725
} as const;
721726

722727
type Screen = DeepValueOf<typeof SCREENS>;

src/components/ButtonWithDropdownMenu/types.ts

+3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ type WorkspaceTaxRatesBulkActionType = DeepValueOf<typeof CONST.POLICY.BULK_ACTI
1818

1919
type ReportExportType = DeepValueOf<typeof CONST.REPORT.EXPORT_OPTIONS>;
2020

21+
type OnboardingHelpType = DeepValueOf<typeof CONST.ONBOARDING_HELP>;
22+
2123
type DropdownOption<TValueType> = {
2224
value: TValueType;
2325
text: string;
@@ -134,4 +136,5 @@ export type {
134136
ButtonWithDropdownMenuProps,
135137
WorkspaceTaxRatesBulkActionType,
136138
ReportExportType,
139+
OnboardingHelpType,
137140
};

src/components/ConfirmModal.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ function ConfirmModal({
161161
shouldSetModalVisibility={shouldSetModalVisibility}
162162
onModalHide={onModalHide}
163163
type={isSmallScreenWidth ? CONST.MODAL.MODAL_TYPE.BOTTOM_DOCKED : CONST.MODAL.MODAL_TYPE.CONFIRM}
164-
innerContainerStyle={image ? styles.pt0 : {}}
164+
innerContainerStyle={styles.pv0}
165165
shouldEnableNewFocusManagement={shouldEnableNewFocusManagement}
166166
restoreFocusType={restoreFocusType}
167167
shouldHandleNavigationBack={shouldHandleNavigationBack}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import React from 'react';
2+
import {View} from 'react-native';
3+
import Text from '@components/Text';
4+
import useStyleUtils from '@hooks/useStyleUtils';
5+
import useThemeStyles from '@hooks/useThemeStyles';
6+
import getButtonState from '@libs/getButtonState';
7+
8+
type DayProps = {
9+
/** Whether day is disabled */
10+
disabled?: boolean;
11+
12+
/** Whether day is selected */
13+
selected?: boolean;
14+
15+
/** Whether day is pressed */
16+
pressed?: boolean;
17+
18+
/** Whether day is hovered */
19+
hovered?: boolean;
20+
21+
/** date to show */
22+
children?: number;
23+
};
24+
25+
function Day({disabled, selected, pressed, hovered, children}: DayProps) {
26+
const themeStyles = useThemeStyles();
27+
const StyleUtils = useStyleUtils();
28+
return (
29+
<View
30+
style={[
31+
themeStyles.calendarDayContainer,
32+
selected ? themeStyles.buttonDefaultBG : {},
33+
!disabled ? StyleUtils.getButtonBackgroundColorStyle(getButtonState(hovered, pressed)) : {},
34+
]}
35+
>
36+
<Text style={disabled ? themeStyles.buttonOpacityDisabled : {}}>{children}</Text>
37+
</View>
38+
);
39+
}
40+
41+
Day.displayName = 'Day';
42+
43+
export default Day;
44+
export type {DayProps};

0 commit comments

Comments
 (0)