Skip to content

Commit

Permalink
Merge branch 'main' into @zfurtak/search-chat-header
Browse files Browse the repository at this point in the history
  • Loading branch information
zfurtak committed Feb 3, 2025
1 parent 55c9e7e commit dea4a26
Show file tree
Hide file tree
Showing 120 changed files with 1,608 additions and 697 deletions.
2 changes: 1 addition & 1 deletion .env.staging
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ EXPENSIFY_PARTNER_PASSWORD=e21965746fd75f82bb66
PUSHER_APP_KEY=268df511a204fbb60884
USE_WEB_PROXY=false
ENVIRONMENT=staging
SEND_CRASH_REPORTS=true
SEND_CRASH_REPORTS=true
28 changes: 28 additions & 0 deletions .github/scripts/checkParser.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash

set -e

ROOT_DIR=$(dirname "$(dirname "$(dirname "${BASH_SOURCE[0]}")")")
cd "$ROOT_DIR" || exit 1

autocomplete_parser_backup="src/libs/SearchParser/autocompleteParser.js.bak"
search_parser_backup="src/libs/SearchParser/searchParser.js.bak"

#Copying the current .js parser files
cp src/libs/SearchParser/autocompleteParser.js "$autocomplete_parser_backup" 2>/dev/null
cp src/libs/SearchParser/searchParser.js "$search_parser_backup" 2>/dev/null

#Running the scripts that generate the .js parser files
npm run generate-search-parser
npm run generate-autocomplete-parser

#Checking if the saved files differ from the newly generated
if ! diff -q "$autocomplete_parser_backup" src/libs/SearchParser/autocompleteParser.js >/dev/null ||
! diff -q "$search_parser_backup" src/libs/SearchParser/searchParser.js >/dev/null; then
echo "The files generated from the .peggy files using the commands: generate-search-parser and generate-autocomplete-parser are not identical to those currently on this branch."
echo "The parser .js files should never be edited manually. Make sure you’ve run locally: npm run generate-search-parser and npm run generate-autocomplete-parser, and committed the changes."
exit 1
else
echo "The files generated from the .peggy files using the commands: generate-search-parser and generate-autocomplete-parser are identical to those currently on this branch."
exit 0
fi
31 changes: 25 additions & 6 deletions .github/workflows/cherryPick.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ jobs:
with:
ref: staging
token: ${{ secrets.OS_BOTIFY_TOKEN }}
submodules: true

- name: Set up git for OSBotify
id: setupGitForOSBotify
Expand Down Expand Up @@ -85,14 +86,13 @@ jobs:
if git cherry-pick -S -x --mainline 1 ${{ steps.getCPMergeCommit.outputs.MERGE_COMMIT_SHA }}; then
echo "🎉 No conflicts! CP was a success, PR can be automerged 🎉"
echo "HAS_CONFLICTS=false" >> "$GITHUB_OUTPUT"
git commit --amend -m "$(git log -1 --pretty=%B)" -m "(CP triggered by ${{ github.actor }})"
else
echo "😞 PR can't be automerged, there are merge conflicts in the following files:"
git --no-pager diff --name-only --diff-filter=U
git add .
GIT_MERGE_AUTOEDIT=no git cherry-pick --continue
git cherry-pick --abort
echo "HAS_CONFLICTS=true" >> "$GITHUB_OUTPUT"
fi
git commit --amend -m "$(git log -1 --pretty=%B)" -m "(CP triggered by ${{ github.actor }})"
- name: Push changes
run: |
Expand All @@ -109,19 +109,38 @@ jobs:
run: |
gh pr create \
--title "🍒 Cherry pick PR #${{ github.event.inputs.PULL_REQUEST_NUMBER }} to staging 🍒" \
--body "🍒 Cherry pick https://github.com/Expensify/App/pull/${{ github.event.inputs.PULL_REQUEST_NUMBER }} to staging 🍒" \
--body \
"🍒 Cherry pick https://github.com/Expensify/App/pull/${{ github.event.inputs.PULL_REQUEST_NUMBER }} to staging 🍒
This PR had conflicts when we tried to cherry-pick it to staging. You'll need to manually perform the cherry-pick, using the following steps:
\`\`\`bash
git fetch
git checkout ${{ github.actor }}-cherry-pick-staging-${{ github.event.inputs.PULL_REQUEST_NUMBER }}-${{ github.run_attempt }}
git cherry-pick -S -x --mainline 1 ${{ steps.getCPMergeCommit.outputs.MERGE_COMMIT_SHA }}
\`\`\`
Then manually resolve conflicts, and commit the change with \`git cherry-pick --continue\`. Lastly, please run:
\`\`\`bash
git commit --amend -m \"$(git log -1 --pretty=%B)\" -m \"(CP triggered by ${{ github.actor }})\"
\`\`\`
That will help us keep track of who triggered this CP. Once all that's done, push your changes with \`git push origin ${{ github.actor }}-cherry-pick-staging-${{ github.event.inputs.PULL_REQUEST_NUMBER }}-${{ github.run_attempt }}\`, and then open this PR for review.
Note that you **must** test this PR, and both the author and reviewer checklist should be completed, just as if you were merging the PR to main." \
--label "Engineering,Hourly" \
--base "staging"
sleep 5
gh pr comment --body \
"This pull request has merge conflicts and can not be automatically merged. :disappointed:
Please manually resolve the conflicts, push your changes, and then request another reviewer to review and merge.
**Important:** There may be conflicts that GitHub is not able to detect, so please _carefully_ review this pull request before approving."
gh pr edit --add-assignee "${{ github.actor }},${{ steps.getCPMergeCommit.outputs.MERGE_ACTOR }}"
ORIGINAL_PR_AUTHOR="$(gh pr view ${{ github.event.inputs.PULL_REQUEST_NUMBER }} --json author --jq .author.login)"
gh pr edit --add-assignee "${{ github.actor }},${{ steps.getCPMergeCommit.outputs.MERGE_ACTOR }},$ORIGINAL_PR_AUTHOR"
env:
GITHUB_TOKEN: ${{ steps.setupGitForOSBotify.outputs.OS_BOTIFY_API_TOKEN }}

- name: Label PR with CP Staging
- name: Label original PR with CP Staging
run: gh pr edit ${{ inputs.PULL_REQUEST_NUMBER }} --add-label 'CP Staging'
env:
GITHUB_TOKEN: ${{ github.token }}
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/createNewVersion.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ jobs:
run: |
cd Mobile-Expensify
git fetch --depth=1 origin main
git checkout main
git reset --hard origin/main
- name: Generate HybridApp version
Expand Down Expand Up @@ -138,14 +139,18 @@ jobs:
- name: Commit new E/App version
run: |
git add \
./Mobile-Expensify
./package.json \
./package-lock.json \
./android/app/build.gradle \
./ios/NewExpensify/Info.plist \
./ios/NewExpensifyTests/Info.plist \
./ios/NotificationServiceExtension/Info.plist
git commit -m "Update version to ${{ steps.bumpVersion.outputs.NEW_VERSION }}"
- name: Update Mobile-Expensify submodule in E/App
run: |
git add Mobile-Expensify
git commit -m "Update Mobile-Expensify submodule version to ${{ steps.bumpVersion.outputs.NEW_VERSION }}"
git push origin main
- name: Announce failed workflow in Slack
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ jobs:
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
GCP_GEOLOCATION_API_KEY: $${{ secrets.GCP_GEOLOCATION_API_KEY_PRODUCTION }}
GCP_GEOLOCATION_API_KEY: ${{ secrets.GCP_GEOLOCATION_API_KEY_PRODUCTION }}

- name: Upload desktop sourcemaps artifact
uses: actions/upload-artifact@v4
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/testBuild.yml
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ jobs:
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
GCP_GEOLOCATION_API_KEY: $${{ secrets.GCP_GEOLOCATION_API_KEY_STAGING }}
GCP_GEOLOCATION_API_KEY: ${{ secrets.GCP_GEOLOCATION_API_KEY_STAGING }}

web:
name: Build and deploy Web
Expand Down
22 changes: 22 additions & 0 deletions .github/workflows/verifyParserFiles.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Check consistency of search parser files

on:
pull_request:
types: [opened, synchronize]
branches-ignore: [staging, production]
paths:
- "src/libs/SearchParser/**"

jobs:
verify:
if: github.actor != 'OSBotify' && github.actor != 'imgbot[bot]'
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: ./.github/actions/composite/setupNode

- name: Verify parser files consistency
run: ./.github/scripts/checkParser.sh
2 changes: 1 addition & 1 deletion Mobile-Expensify
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
versionCode 1009009202
versionName "9.0.92-2"
versionCode 1009009303
versionName "9.0.93-3"
// Supported language variants must be declared here to avoid from being removed during the compilation.
// This also helps us to not include unnecessary language variants in the APK.
resConfigs "en", "es"
Expand Down
14 changes: 14 additions & 0 deletions assets/images/customEmoji/global-create.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,19 @@ A CSV upload is a manual method for importing credit card transactions into Expe

---
# CSV Upload: How do I import credit card transactions using a CSV?
1. Download your card transactions in a CSV, OFX, QFX, or XLS format from your bank.
2. Format the file to include the card number, date, merchant, amount, and currency.
1. Download your card transactions from your bank in CSV, OFX, QFX, or XLS format.
2. Format the CSV for upload using [this template](https://s3-us-west-1.amazonaws.com/concierge-responses-expensify-com/uploads%2F1594908368712-Best+Example+CSV+for+Domains.csv) as a guide -- be sure to include the card number, date, merchant, amount, and currency.
- You can also add mapping for Categories and Tags, but those parameters are optional.

![Your CSV template should include, at a minimum, a column for the card number, posted date, merchant, posted amount, and posted currency.](https://help.expensify.com/assets/images/csv-01.png){:width="100%"}

3. Go to **Settings > Domains > [Domain Name] > Company Cards > Manage/Import CSV**.
4. Upload the file and map the fields to Expensify’s requirements.
5. Review the Output Preview for errors and submit the file.


![Click Manage/Import CSV located in the top right between the Issue Virtual Card button and the Import Card button.](https://help.expensify.com/assets/images/csv-02.png){:width="100%"}

---
# Assign Cards: How do I assign cards to employees?
1. Go to **Settings > Domains > [Domain Name] > Company Cards**.
Expand All @@ -89,6 +96,10 @@ A CSV upload is a manual method for importing credit card transactions into Expe
4. (Optional) Set a transaction start date.
5. Click **Assign** to complete the process.

![Click the dropdown located right below the Imported Cards title near the top of the page. Then select a card from the list.](https://help.expensify.com/assets/images/csv-03.png){:width="100%"}

![Under the Company Cards tab on the left, you'll use the dropdown menu to select a card and beneath that, you'll click Assign New Cards]({{site.url}}/assets/images/CompanyCards_Assign.png){:width="100%"}

---
# Unassign Cards: How do I unassign cards?
1. Go to **Settings > Domains > [Domain Name] > Company Cards**.
Expand All @@ -97,18 +108,43 @@ A CSV upload is a manual method for importing credit card transactions into Expe

_**Note: Unassigning a card deletes all open or unreported expenses linked to it.**_

![Click the Actions button to the right of the card and select Unassign.]({{site.url}}/assets/images/CompanyCards_Unassign.png){:width="100%"}

---
# Configure Company Card Settings
1. Go to **Settings > Domains > [Domain Name] > Company Cards > Settings**.
2. Adjust preferences for:
- **Preferred Workspace**: Ensures transactions are reported to a specific workspace.
- **Reimbursable Preference**: Controls whether expenses are flagged as reimbursable or non-reimbursable.
- **Liability Type**: Sets corporate or personal liability for expenses. Corporate liability prevents users from deleting company card expenses, while personal liability allows users to manage and delete expenses directly.
- **Liability Type**: Set the corporate or personal liability settings for company card expenses. Corporate liability prevents users from deleting company card expenses, while personal liability allows users to manage and delete their company card expenses.
3. Save the settings to apply changes.

**Tip**: For businesses using accounting integrations like QuickBooks or NetSuite, connect the cards to export expenses to specific general ledger (GL) accounts via the "Edit Exports" option.
![Near the top right, click the Settings tab that is located between the Card List and Reconciliation tabs.](https://help.expensify.com/assets/images/compcard-01.png){:width="100%"}

## Export Company Card Expenses to a Connected Accounting Integration: Centralized General Ledger Account

For businesses using accounting integrations like QuickBooks or NetSuite, connect the cards to export expenses to specific general ledger (GL) accounts via the "Edit Exports" option.

![Find the desired card in the table. In that same row, click Edit Exports.](https://help.expensify.com/assets/images/cardfeeds-02.png){:width="100%"}

**To export credit card expenses to a pooled GL account:**
1. Navigate to **Settings > Workspaces**.
2. Select the appropriate **Workspace**.
3. Open the **Connections** tab.
4. Under **Accounting Integrations**, click **Configure** next to the relevant integration.
5. In the **Non-reimbursable Export** section, select **Credit Card / Charge Card / Bank Transaction**.
6. Review the **Export Settings** page to ensure proper expense report export to NetSuite.
7. Choose the **Vendor/Liability Account** for exporting all non-reimbursable expenses.

## Exporting to Individual General Ledger Accounts

1. Navigate to **Settings > Domains**.
2. Select the appropriate **Domain**.
3. Click **Edit Exports** next to the relevant card.
4. Select the **General Ledger (GL) Account** for expense exports.

---

# FAQ

## Missing Transactions: Why aren’t all transactions appearing?
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,53 @@
---
title: Consolidated Domain Billing
description: Consolidated Domain Billing allows organizations to have different billing owners with only one person being billed for all paid workspaces.
description: Learn how to enable and manage Consolidated Domain Billing, allowing one billing owner to cover all paid workspaces under a verified domain.
---
<!-- The lines above are required by Jekyll to process the .md file -->

# Overview
If your organization requires that different workspaces have different billing owners, but only one person should pay the Expensify bill each month, you can enable Consolidated Domain Billing.
# How to enable Consolidated Domain Billing
Consolidated Domain Billing is a domain-level feature, so to access this setting, you’ll first need to claim and verify your domain. You can do this by heading to **Settings > Domains > Domain Name** > clicking on a setting such as **Groups** > and then clicking **Verify**.
Consolidated Domain Billing allows organizations to have different billing owners for workspaces while ensuring that only one person is billed for all paid workspaces within a verified domain.

---

# Enabling Consolidated Domain Billing
To enable this feature, you must first claim and verify your domain:

1. Go to **Settings > Domains**.
2. Select your domain.
3. Click on a setting such as **Groups**.
4. Click **Verify**.

Once your domain is verified, enable Consolidated Domain Billing:

1. Navigate to **Settings > Domains > [Your Domain]**.
2. Select **Domain Admins > Primary Contact and Billing**.
3. Toggle **Consolidated Domain Billing** on.

Once the domain is verified, you can enable Consolidated Domain Billing under **Settings > Domains > Domain Name > Domain Admins > Primary Contact and Billing**.
# How to use Consolidated Domain Billing
When a Domain Admin enables Consolidated Domain Billing, all Group workspaces owned by any user with an email address matching the domain will get billed to the Consolidated Domain Billing owner’s account.
# Deep Dive
## Consolidated Domain Billing best practices
If you don’t have multiple billing owners across your organization, or if you want to keep billing separate for any reason, then this feature isn’t necessary.
---

# How It Works
When a **Domain Admin** enables Consolidated Domain Billing:

If you have an Annual Subscription and enable Consolidated Domain Billing, the Consolidated Domain Billing feature will gather the amounts due for each Group workspace Billing Owner (listed under **Settings > Workspaces > Group**). To make full use of the Annual Subscription for all workspaces in your domain, you should also be the billing owner for all Group workspaces.
- All **Group Workspaces** owned by users with an email address matching the domain will be billed to the **Primary Contact** listed under **Domain Admins**.
- Individual workspace billing owners will no longer receive separate charges.

---

# Best Practices
- **When to Use It**: If multiple billing owners exist in your organization but you want a single, consolidated bill.
- **When to Avoid It**: If you need to keep workspace billing separate for accounting or financial tracking purposes.
- **Annual Subscription Considerations**:
- If you have an **Annual Subscription**, Consolidated Domain Billing will combine the amounts due for each Group workspace billing owner.
- To maximize savings, the **Primary Contact** should also be the billing owner for all Group Workspaces.

---

{% include faq-begin.md %}
# FAQ

## How do I take over the billing of a workspace with Consolidated Domain Billing enabled?
You’ll have to toggle off Consolidated Domain Billing, take over ownership of the workspace, and then toggle it back on.
## How do I take over the billing of a workspace with Consolidated Domain Billing enabled?
1. Toggle off **Consolidated Domain Billing**.
2. Take ownership of the workspace.
3. Toggle **Consolidated Domain Billing** back on.

## Can I use Consolidated Domain Billing to cover the bill for some workspaces, but not others?
No, this feature means that you’ll be paying the bill for all domain members who choose a subscription.
## Can I cover the bill for some workspaces but not others?
No, enabling this feature means you will be billed for **all** domain members who choose a subscription.

{% include faq-end.md %}
Loading

0 comments on commit dea4a26

Please sign in to comment.