Skip to content

Commit 0b1309f

Browse files
committed
Merge branch 'main' of github.com:Expensify/App into beaman/612787-app-export-explain-button
2 parents d03fdcf + 39b4ff7 commit 0b1309f

165 files changed

Lines changed: 4196 additions & 1751 deletions

File tree

Some content is hidden

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

.github/actions/javascript/getPullRequestIncrementalChanges/index.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12647,6 +12647,19 @@ class Git {
1264712647
throw new Error(`Failed to get file content from git: ${error instanceof Error ? error.message : String(error)}`);
1264812648
}
1264912649
}
12650+
/**
12651+
* Abbreviated hash for HEAD in the current working directory.
12652+
*
12653+
* @returns Short commit hash, or `unknown` when not a git repo or git fails.
12654+
*/
12655+
static getHeadShort() {
12656+
try {
12657+
return execSync('git rev-parse --short HEAD').trim();
12658+
}
12659+
catch {
12660+
return 'unknown';
12661+
}
12662+
}
1265012663
/**
1265112664
* Ensure a git reference is available locally, fetching it if necessary.
1265212665
*

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ yarn-error.log
5858
# Bundled code
5959
dist/
6060

61+
# Generated eslint-report HTML (npm run eslint-report)
62+
reports/
63+
6164
# BUCK
6265
buck-out/
6366
\.buckd/

Mobile-Expensify

android/app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ android {
111111
minSdkVersion rootProject.ext.minSdkVersion
112112
targetSdkVersion rootProject.ext.targetSdkVersion
113113
multiDexEnabled rootProject.ext.multiDexEnabled
114-
versionCode 1009036413
115-
versionName "9.3.64-13"
114+
versionCode 1009036422
115+
versionName "9.3.64-22"
116116
// Supported language variants must be declared here to avoid from being removed during the compilation.
117117
// This also helps us to not include unnecessary language variants in the APK.
118118
resConfigs "en", "es"

contributingGuides/LINTING.md

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ npm run lint -- --show-warnings
1919

2020
# Continuously re-lint changed files as you edit:
2121
npm run lint-watch
22+
23+
# HTML dashboard: seatbelt baseline broken down by rule and by file:
24+
npm run eslint-report
2225
```
2326

2427
Prefer `npm run lint` (or `lint-changed` / `lint -- <files>`) over raw `npx eslint` invocations. Those wrappers increase the memory allocation to prevent OOM errors, and also include caching and concurrency flags for faster linting.
@@ -63,6 +66,18 @@ If you're iterating specifically on a CI failure and you already know which file
6366
npm run lint -- src/components/Foo/index.tsx src/libs/bar.ts
6467
```
6568

69+
### "What if I want to see lint errors broken down by type or by file?"
70+
71+
Use `npm run eslint-report`. It will show an HTML report of current lint errors in the project (populated from `eslint.seatbelt.tsv`)
72+
73+
```bash
74+
npm run eslint-report
75+
```
76+
77+
![Seatbelt report: breakdown by ESLint rule](https://github.com/user-attachments/assets/2e1cc9dd-155e-4975-8a1f-365c5a830f27)
78+
79+
![Seatbelt report: breakdown by file](https://github.com/user-attachments/assets/e4b4bf50-ae5b-416d-96ff-0357e5fe5b59)
80+
6681
### "I fixed an existing baselined error"
6782

6883
Just run `npm run lint` (or `npm run lint-changed`) locally. Seatbelt notices the count went down and passes. **It does not rewrite `config/eslint/eslint.seatbelt.tsv` locally** — the config sets `readOnly: !process.env.CI`, so the TSV is only rewritten in CI. After your PR merges, the lint job on `main` re-runs, writes the tightened TSV, and OSBotify commits it back to `main` for you.
@@ -71,17 +86,30 @@ No TSV commit required on your end.
7186

7287
### "I added a new error and can't easily fix it right now"
7388

74-
The default assumption is that you fix it. If you genuinely need to land code that trips a baselined rule and the fix is out of scope, you have two options, in order of preference:
89+
The default assumption is that you fix it. If you genuinely need to land code that trips a baselined rule and the fix is out of scope, you have two options:
7590

76-
1. **Suppress the specific occurrence** with an `eslint-disable-next-line <rule>` comment and a justification. See [`CONSISTENCY-5`](../.claude/skills/coding-standards/rules/consistency-5-justify-eslint-disable.md).
77-
2. **Widen the seatbelt baseline** for that file/rule with `SEATBELT_INCREASE`:
91+
1. **Widen the seatbelt baseline** for that file/rule with `SEATBELT_INCREASE` — preferred for **temporary** suppressions (e.g. the fix requires a large refactor that is out of scope for the current PR, or you're intentionally deferring cleanup):
7892

7993
```bash
8094
# Allow the new count for one rule:
8195
SEATBELT_INCREASE=@typescript-eslint/no-deprecated npm run lint
8296
```
8397

84-
That will modify `config/eslint/eslint.seatbelt.tsv`. **Always commit the diff alongside your code**, and expect a reviewer to ask you why a fix wasn't feasible.
98+
That will modify `config/eslint/eslint.seatbelt.tsv`. **Always commit the diff alongside your code**, and expect a reviewer to ask you why a fix wasn't feasible. Because the violation stays visible in the baseline, it can still be fixed later.
99+
100+
2. **Suppress the specific occurrence** with an `eslint-disable-next-line <rule>` comment and a justification — preferred for **permanent** suppressions, where you genuinely believe the lint rule is wrong for that specific case and you don't expect the violation to ever be fixed. See [`CONSISTENCY-5`](../.claude/skills/coding-standards/rules/consistency-5-justify-eslint-disable.md).
101+
102+
> **Which should I use?** Reach for `SEATBELT_INCREASE` when the error is merely inconvenient to fix right now. Reach for `eslint-disable-next-line` only when you are making a deliberate, permanent exception — i.e. you're certain the rule simply doesn't apply to this particular case. `eslint-disable` comments hide violations from the baseline entirely, so they should only be used when the suppression is intentional and indefinite.
103+
104+
### "I moved or renamed a file without fixing its existing errors"
105+
106+
When you move or rename a file, seatbelt's baseline entry for the old path is no longer matched. Even though you made no logical change to the code, the violations now appear under a path the baseline doesn't know about, so CI will fail. Use `SEATBELT_INCREASE` to re-baseline the file under its new name:
107+
108+
```bash
109+
SEATBELT_INCREASE=<rule-id> npm run lint
110+
```
111+
112+
Commit the updated `config/eslint/eslint.seatbelt.tsv` alongside the rename. The old path will be removed from the TSV automatically by the lint job on `main` after your PR merges.
85113

86114
### "I'm enabling a new rule repo-wide"
87115

cspell.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,7 @@
422422
"McAfee",
423423
"mchmod",
424424
"MCTEST",
425+
"Menlo",
425426
"mechler",
426427
"mediumitalic",
427428
"memberof",
@@ -505,6 +506,7 @@
505506
"NTSB",
506507
"Nuevo",
507508
"nullptr",
509+
"nums",
508510
"numberformat",
509511
"objc",
510512
"objdump",
@@ -921,6 +923,7 @@
921923
"Kolkata"
922924
],
923925
"ignorePaths": [
926+
".gitignore",
924927
"src/languages/de.ts",
925928
"src/languages/es.ts",
926929
"src/languages/fr.ts",
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
---
2+
title: Integrate Deel and Expensify
3+
description: Learn how to integrate Expensify with Deel to automate expense syncing for employee reimbursements.
4+
keywords: [New Expensify, integrate Deel Expensify, Expensify Deel integration, expense syncing Deel, reimbursements Deel Expensify, approval workflow Deel]
5+
internalScope: Audience is Workspace Admins and Deel Organization Managers. Covers integrating Expensify with Deel and understanding how the sync works. Does not cover employee or contractor usage within Deel.
6+
---
7+
8+
# Integrate Deel and Expensify
9+
10+
Expensify’s API allows you to integrate with tools like Deel to automate expense syncing and reimbursements.
11+
12+
This integration enables Expensify to act as the source of truth for employee expenses, while Deel handles reimbursement processing. The setup is self-serve and typically managed by your internal team.
13+
14+
To begin, review Expensify's [Integration Server Documentation](https://integrations.expensify.com/Integration-Server/doc/#introduction) to understand how Expensify’s API works and how to authenticate your account.
15+
16+
If you are an employee or contractor using Expensify within your company, refer to:
17+
18+
- [Employee Guide to Using Expensify with Deel](https://help.letsdeel.com/hc/en-gb/articles/7123572847761-Employee-s-Guide-to-Using-Expensify-With-Deel)
19+
- [Contractor Guide to Using Expensify with Deel](https://help.letsdeel.com/hc/en-gb/articles/9640208314897-How-Contractors-Can-Use-Expensify-With-Deel)
20+
21+
---
22+
23+
## Who can integrate Deel and Expensify
24+
25+
- Workspace Admins in Expensify
26+
- Organization Manager permissions in Deel
27+
28+
**Prerequisites:**
29+
- Deel Organization Manager permissions
30+
- Expensify Admin permissions for the selected Workspaces
31+
32+
---
33+
34+
## How to integrate Deel and Expensify
35+
36+
The integration is configured using Expensify’s API and completed within Deel. For a step-by-step guide, refer to Deel's setup guide: [How To Set Up The Expensify Integration On Deel For EOR Employees And Contractors](https://help.letsdeel.com/hc/en-gb/articles/5871319525521-How-To-Set-Up-The-Expensify-Integration-On-Deel-For-EOR-Employees-And-Contractors).
37+
38+
---
39+
40+
## How the Deel integration with Expensify works
41+
42+
By connecting Expensify to Deel, you can use Expensify’s approval workflows to control which expenses are eligible for reimbursement.
43+
44+
- Deel scans for approved expenses from matched users in selected Workspaces
45+
- Only approved expenses in Expensify are eligible for syncing
46+
- Expenses are imported into Deel for reimbursement processing
47+
48+
Key details:
49+
50+
- **One-way sync:** Expenses approved in Expensify sync to Deel. Expenses created in Deel do not sync back to Expensify.
51+
- **Approval workflow:** Only approved expenses are synced
52+
- **Sync timing:** Expense syncing is not immediate and depends on Deel processing
53+
54+
---
55+
56+
## What happens after you integrate Deel and Expensify
57+
58+
- Deel continuously scans the connected Expensify Workspaces
59+
- Approved expenses are synced to Deel
60+
- Expenses are processed in Deel for reimbursement
61+
- Expensify remains the system of record for expense data
62+
- Sync timing may vary and is not immediate
63+
64+
---
65+
66+
# FAQ
67+
68+
## Can expenses sync from Deel back to Expensify?
69+
70+
No. This is a one-way integration. Expenses only sync from Expensify to Deel.
71+
72+
## Why aren’t my expenses syncing?
73+
74+
Common reasons include:
75+
- The expense is not approved in Expensify
76+
- The user is not mapped between Deel and Expensify
77+
- The Workspace is not connected
78+
- The integration setup is incomplete
79+
80+
## Do employees or contractors need to do anything?
81+
82+
Employees and contractors submit expenses in Expensify as usual. Admins manage the integration and approval workflow.
83+
84+
## Does Expensify support the integration setup?
85+
86+
Expensify can help with basic troubleshooting, but your internal team is responsible for setting up and maintaining the API integration.
87+
88+
## Where can I learn more about the Deel setup process?
89+
90+
Review Deel’s official guide for setting up the Expensify integration and managing expense syncing: [How To Set Up The Expensify Integration On Deel For EOR Employees And Contractors](https://help.letsdeel.com/hc/en-gb/articles/5871319525521-How-To-Set-Up-The-Expensify-Integration-On-Deel-For-EOR-Employees-And-Contractors).
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
---
2+
title: Egencia
3+
description: Learn how to integrate Egencia with Expensify to automatically import travel booking receipts and expenses.
4+
keywords: [Egencia, travel booking, Expensify Classic]
5+
---
6+
7+
8+
Expensify’s API helps connect your account to third-party tools like NetSuite, Xero, and even internal systems like Workday. This guide includes tips, usage examples, and common troubleshooting questions — many sourced from customers who’ve done it before.
9+
10+
---
11+
12+
# Getting Started
13+
14+
To start using the API, review our full [Integration Server Manual](https://integrations.expensify.com/Integration-Server/doc/#introduction).
15+
16+
**Note:** The API is a self-serve tool. Your internal team will need to manage setup and maintenance. While Concierge can assist with basic troubleshooting, hands-on support may vary by team or account manager.
17+
18+
[Egencia](https://www.egencia.com/en/) is a business travel booking platform. Integrating Egencia with Expensify allows travel bookings to be automatically imported as expenses, ensuring seamless expense tracking.
19+
20+
## Requirements
21+
To use the Egencia integration, you must have:
22+
- A **Control Workspace**
23+
- A **verified Domain**
24+
25+
---
26+
27+
# How Egencia Works with Expensify
28+
When an employee books travel through Egencia:
29+
- The receipt and itinerary are automatically imported into the traveler’s Expensify account, eliminating the need for manual entry.
30+
- If the traveler uses a company credit card, the Egencia receipt automatically merges with the corresponding credit card transaction.
31+
- Travel details are also accessible in the **Trips** section of the Expensify mobile app.
32+
33+
---
34+
35+
# Enabling the Egencia Feed
36+
A file feed is an automated data transfer from Egencia to Expensify.
37+
38+
To enable the feed:
39+
1. Contact your Egencia account manager.
40+
2. Request to enable the Expensify feed for your organization.
41+
42+
**Note:** Egencia controls the feed setup process.
43+
44+
---
45+
46+
# Connecting a Central Purchasing Account
47+
If your company uses a **central purchasing account**, you can forward all Egencia booking receipts to a single Expensify account.
48+
49+
## Steps to Enable a Central Purchasing Account
50+
1. **Open a chat with Concierge** in Expensify.
51+
2. **Provide the central account email** and request activation. Example message:
52+
> "Please enable Central Purchasing Account for our Egencia feed. The account email is: `youraccount@yourdomain.com`."
53+
54+
## How It Works
55+
- Booking receipts will be sent to **both** the traveler and the central account.
56+
- The receipt in the traveler’s account is marked as a **reservation expense**, which:
57+
- Is **non-reimbursable**.
58+
- **Will not be exported** to an integrated accounting system.
59+

0 commit comments

Comments
 (0)