Skip to content

Commit

Permalink
Merge branch 'main' into dsilva_margelo-test-e2e
Browse files Browse the repository at this point in the history
  • Loading branch information
danieldoglas committed Apr 22, 2024
2 parents 898bd17 + 98d85e0 commit 051673b
Show file tree
Hide file tree
Showing 132 changed files with 2,844 additions and 1,107 deletions.
64 changes: 64 additions & 0 deletions .github/scripts/detectRedirectCycle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import {parse} from 'csv-parse';
import fs from 'fs';

const parser = parse();

const adjacencyList: Record<string, string[]> = {};
const visited: Map<string, boolean> = new Map<string, boolean>();
const backEdges: Map<string, boolean> = new Map<string, boolean>();

function addEdge(source: string, target: string) {
if (!adjacencyList[source]) {
adjacencyList[source] = [];
}
adjacencyList[source].push(target);
}

function isCyclic(currentNode: string): boolean {
visited.set(currentNode, true);
backEdges.set(currentNode, true);

// Do a depth first search for all the neighbours. If a node is found in backedge, a cycle is detected.
const neighbours = adjacencyList[currentNode];
if (neighbours) {
for (const node of neighbours) {
if (!visited.has(node)) {
if (isCyclic(node)) {
return true;
}
} else if (backEdges.has(node)) {
return true;
}
}
}

backEdges.delete(currentNode);

return false;
}

function detectCycle(): boolean {
for (const [node] of Object.entries(adjacencyList)) {
if (!visited.has(node)) {
if (isCyclic(node)) {
const cycle = Array.from(backEdges.keys());
console.log(`Infinite redirect found in the cycle: ${cycle.join(' -> ')} -> ${node}`);
return true;
}
}
}
return false;
}

fs.createReadStream(`${process.cwd()}/docs/redirects.csv`)
.pipe(parser)
.on('data', (row) => {
// Create a directed graph of sourceURL -> targetURL
addEdge(row[0], row[1]);
})
.on('end', () => {
if (detectCycle()) {
process.exit(1);
}
process.exit(0);
});
19 changes: 15 additions & 4 deletions .github/scripts/verifyRedirect.sh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,22 @@

declare -r REDIRECTS_FILE="docs/redirects.csv"

declare -r RED='\033[0;31m'
declare -r GREEN='\033[0;32m'
declare -r NC='\033[0m'

duplicates=$(awk -F, 'a[$1]++{print $1}' $REDIRECTS_FILE)
if [[ -n "$duplicates" ]]; then
echo "${RED}duplicate redirects are not allowed: $duplicates ${NC}"
exit 1
fi

if [[ -z "$duplicates" ]]; then
exit 0
npm run detectRedirectCycle
DETECT_CYCLE_EXIT_CODE=$?
if [[ DETECT_CYCLE_EXIT_CODE -eq 1 ]]; then
echo -e "${RED}The redirects.csv has a cycle. Please remove the redirect cycle because it will cause an infinite redirect loop ${NC}"
exit 1
fi

echo "duplicate redirects are not allowed: $duplicates"
exit 1
echo -e "${GREEN}The redirects.csv is valid!${NC}"
exit 0
4 changes: 2 additions & 2 deletions .github/workflows/deployExpensifyHelp.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ jobs:

- name: Create docs routes file
run: ./.github/scripts/createDocsRoutes.sh
- name: Check duplicates in redirect.csv

- name: Check for duplicates and cycles in redirects.csv
run: ./.github/scripts/verifyRedirect.sh

- name: Build with Jekyll
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/e2ePerformanceTests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ jobs:
if: ${{ !fromJSON(steps.getPullRequestDetails.outputs.IS_MERGED) }}
id: getMergeCommitShaIfUnmergedPR
run: |
git merge --allow-unrelated-histories --no-commit ${{ steps.getPullRequestDetails.outputs.HEAD_COMMIT_SHA }}
git merge --allow-unrelated-histories -X ours --no-commit ${{ steps.getPullRequestDetails.outputs.HEAD_COMMIT_SHA }}
git checkout ${{ steps.getPullRequestDetails.outputs.HEAD_COMMIT_SHA }}
env:
GITHUB_TOKEN: ${{ github.token }}
Expand Down
8 changes: 8 additions & 0 deletions .well-known/apple-app-site-association
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
"/": "/split/*",
"comment": "Split Expense"
},
{
"/": "/submit/*",
"comment": "Submit Expense"
},
{
"/": "/request/*",
"comment": "Submit Expense"
Expand All @@ -76,6 +80,10 @@
"/": "/search/*",
"comment": "Search"
},
{
"/": "/pay/*",
"comment": "Pay someone"
},
{
"/": "/send/*",
"comment": "Pay someone"
Expand Down
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
versionCode 1001046307
versionName "1.4.63-7"
versionCode 1001046321
versionName "1.4.63-21"
// 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
4 changes: 4 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/bank-account"/>
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/iou"/>
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/request"/>
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/submit"/>
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/enable-payments"/>
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/statements"/>
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/concierge"/>
Expand All @@ -70,6 +71,7 @@
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/new"/>
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/search"/>
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/send"/>
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/pay"/>
<data android:scheme="https" android:host="new.expensify.com" android:pathPrefix="/money2020"/>

<!-- Staging URLs -->
Expand All @@ -81,6 +83,7 @@
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/bank-account"/>
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/iou"/>
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/request"/>
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/submit"/>
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/enable-payments"/>
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/statements"/>
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/concierge"/>
Expand All @@ -89,6 +92,7 @@
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/new"/>
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/search"/>
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/send"/>
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/pay"/>
<data android:scheme="https" android:host="staging.new.expensify.com" android:pathPrefix="/money2020"/>
</intent-filter>
</activity>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
---
title: Enable and set up expense violations
description: Set up rules for expenses and enable violations
---
<div id="expensify-classic" markdown="1">

Expensify automatically detects expense errors or discrepancies as violations that must be corrected. You can also set rules for a workspace that will trigger a violation if the rule is not met. These rules can be set for categories, tags, and even for specific domain groups.

When reviewing submitted expense reports, approvers will see violations highlighted with an exclamation mark. There are two types of violations:
- **Yellow**: Automated highlights that require attention but may not require corrective action. For example, if a receipt was SmartScanned and then the amount was modified, a yellow violation will be added to call out the change for review.
- **Red**: Violations directly tied to your workspace settings. These violations must be addressed before the report can be submitted and reimbursed.

You can hover over the icon to see a brief description, and you can find more detailed information below the list of expenses.

{% include info.html %}
If your workspace has automations set to automatically submit reports for approval, the report that contains violations will not be submitted automatically until the violations are corrected. (However, if a comment is added to an expense, it will override the violation as the member is providing a reason for submission *unless* domain workspace rules are set to be strictly enforced, as detailed near the bottom of this article.)
{% include end-info.html %}

# Enable or disable expense violations

1. Hover over Settings, then click **Workspaces**.
2. Click the **Group** tab on the left.
3. Click the desired workspace name.
4. Click the **Expenses** tab on the left.
5. Click the “Enable violations” toggle.
6. If desired, enter the expense rules that will be used to create violations:
- **Max expense age (days)**: How old an expense can be
- **Max expense amount**: How much a single expense can cost
- **Receipt required amount**: How much a single expense can cost before a receipt is required

{% include info.html %}
Expensify includes certain system mandatory violations that can't be disabled, even if your policy has violations turned off.
{% include end-info.html %}

# Set category rules

Admins on a Control workspace can enable specific rules for each category, including setting expense caps for specific categories, requiring receipts, and more. These rules can allow you to have a default expense limit of $2,500 but to only allow a daily entertainment limit of $150 per person. You can also choose to not require receipts for mileage or per diem expenses.

To set up category rules,
1. Hover over Settings, then click **Workspaces**.
2. Click the **Group** tab on the left.
3. Click the desired workspace name.
4. Click the **Categories** tab on the left.
5. Click **Edit** to the right of the category.
6. Enter your category rules, as desired:
- **GL Code and Payroll Code**: You can add general ledger (GL) or payroll codes to the category for accounting. GL codes populate automatically if you have an accounting integration connected with Expensify.
- **Max Amount**: You can set specific expense caps for the expense category. Use the Limit Type dropdown to determine if the amount is set per individual expense or per day, then enter the maximum amount into this field.
- **Receipts**: You can determine whether receipts are required for the category. For example, many companies disable receipt requirements for toll expenses.
- **Description**: You can determine whether a description is required for expenses under this category.
- **Description Hint**: You can add a hint in the description field to prompt the expense creator on what they should enter into the description field for expenses under this category.
- **Approver**: You can set a specific approver for expenses labeled with this category.

If users are in violation of these rules, the violations will be shown in red on the report.

{% include info.html %}
If Scheduled Submit is enabled on a workspace, expenses with category violations will not be auto-submitted unless the expense has a comment added.
{% include end-info.html %}

# Make categories required

This means all expenses must be coded with a Category.

1. Hover over Settings, then click **Workspaces**.
2. Click the **Group** tab on the left.
3. Click the desired workspace name.
4. Click the **Categories** tab on the left.
5. Enable the “People must categorize expenses” toggle.

Each Workspace Member will now be required to select a category for their expense. If they do not select a category, the report will receive a violation, which can prevent submission if Scheduled Submit is enabled.

# Make tags required

1. Hover over Settings, then click **Workspaces**.
2. Click the **Group** tab on the left.
3. Click the desired workspace name.
4. Click the **Tags** tab on the left.
5. Enable the “People must tag expenses” toggle.

Each Workspace Member will now be required to select a tag for their expense before they’re able to submit it.

# Require strict compliance by domain group

You can require strict compliance to require members of a specific domain group to submit reports that meet **all** workspace rules before they can submit their expense report—even if they add a note. Every rule and regulation on the workspace must be met before a report can be submitted.

{% include info.html %}
This will prevent members from submitting any reports where a manager has granted them a manual exception for any of the workspace rules.
{% include end-info.html %}

To enable strict domain group compliance for reports,

1. Hover over Settings, then click **Domains**.
2. Click the **Groups** tab on the left.
3. Click **Edit** to the right of the desired workspace name.
4. Enable the “Strictly enforce expense workspace rules” toggle.

# FAQs

**Why can’t my employees see the categories on their expenses?**

The employee may have their default workspace set as their personal workspace. Look under the details section on top right of the report to ensure it is being reported under the correct workspace.

**Will the account numbers from our accounting system (QuickBooks Online, Sage Intacct, etc.) show in the category list for employees?**

The general ledger (GL) account numbers are visible only for Workspace Admins in the workspace settings when they are part of a control workspace. This information is not visible to other members of the workspace. However, if you wish to have this information available to your employees when they are categorizing their expenses, you can edit the account name in your accounting software to include the GL number (for example, Accounts Payable - 12345).

**What causes a category violation?**

- An expense is categorized with a category that is not included in the workspace's categories. This may happen if the employee creates an expense under the wrong workspace, which will cause a "category out of workspace" violation.
- If the workspace categories are being imported from an accounting integration and they’ve been updated in the accounting system but not in Expensify, this can cause an old category to still be in use on an open report which would throw a violation on submission. Simply reselect a proper category to clear violation.

</div>
4 changes: 3 additions & 1 deletion docs/redirects.csv
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ https://help.expensify.com/articles/new-expensify/payments/Request-Money,https:/
https://help.expensify.com/articles/expensify-classic/workspace-and-domain-settings/tax-tracking,https://help.expensify.com/articles/expensify-classic/expenses/expenses/Apply-Tax
https://help.expensify.com/articles/expensify-classic/copilots-and-delegates/User-Roles.html,https://help.expensify.com/expensify-classic/hubs/copilots-and-delegates/
https://help.expensify.com/articles/expensify-classic/expensify-billing/Billing-Owner,https://help.expensify.com/articles/expensify-classic/workspaces/Assign-billing-owner-and-payment-account
https://help.expensify.com/articles/expensify-classic/expensify-billing/Billing-Owner.html,https://help.expensify.com/articles/expensify-classic/workspaces/Assign-billing-owner-and-payment-account
https://help.expensify.com/articles/expensify-classic/insights-and-custom-reporting/Other-Export-Options.html,https://help.expensify.com/articles/expensify-classic/spending-insights/Other-Export-Options
https://help.expensify.com/articles/expensify-classic/bank-accounts-and-credit-cards/business-bank-accounts/Business-Bank-Accounts-AUD,https://help.expensify.com/articles/expensify-classic/connect-credit-cards/Global-Reimbursements
https://help.expensify.com/expensify-classic/hubs/bank-accounts-and-credit-cards,https://help.expensify.com/expensify-classic/hubs/
Expand Down Expand Up @@ -123,7 +124,6 @@ https://help.expensify.com/articles/expensify-classic/billing-and-subscriptions/
https://help.expensify.com/articles/expensify-classic/billing-and-subscriptions/Tax-Exempt,https://help.expensify.com/articles/expensify-classic/expensify-billing/Tax-Exempt
https://help.expensify.com/articles/expensify-classic/copilots-and-delegates/Approving-Reports,https://help.expensify.com/expensify-classic/hubs/reports/
https://help.expensify.com/articles/expensify-classic/copilots-and-delegates/Invite-Members,https://help.expensify.com/articles/expensify-classic/workspaces/Invite-members-and-assign-roles
https://help.expensify.com/articles/expensify-classic/copilots-and-delegates/Removing-Members,https://help.expensify.com/articles/expensify-classic/copilots-and-delegates/Removing-Members
https://help.expensify.com/articles/expensify-classic/expense-and-report-features/Attendee-Tracking,https://help.expensify.com/articles/expensify-classic/expenses/Track-group-expenses
https://help.expensify.com/articles/expensify-classic/expense-and-report-features/Currency,https://help.expensify.com/articles/expensify-classic/workspaces/Currency
https://help.expensify.com/articles/expensify-classic/expense-and-report-features/Expense-Rules,https://help.expensify.com/articles/expensify-classic/expenses/Expense-Rules
Expand Down Expand Up @@ -158,3 +158,5 @@ https://help.expensify.com/articles/expensify-classic/workspaces/Budgets,https:/
https://help.expensify.com/articles/expensify-classic/workspaces/Categories,https://help.expensify.com/articles/expensify-classic/workspaces/Create-categories
https://help.expensify.com/articles/expensify-classic/workspaces/Tags,https://help.expensify.com/articles/expensify-classic/workspaces/Create-tags
https://help.expensify.com/expensify-classic/hubs/manage-employees-and-report-approvals,https://help.expensify.com/articles/expensify-classic/copilots-and-delegates/Approval-Workflows
https://help.expensify.com/articles/expensify-classic/reports/Report-Audit-Log-and-Comments,https://help.expensify.com/articles/expensify-classic/reports/Print-or-download-a-report
https://help.expensify.com/articles/expensify-classic/reports/The-Reports-Page,https://help.expensify.com/articles/expensify-classic/reports/Report-statuses
2 changes: 1 addition & 1 deletion docs/sitemap.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ layout:
{% assign pages = site.html_pages | where_exp:'doc','doc.sitemap != false' | where_exp:'doc','doc.url != "/404.html"' %}
{% for page in pages %}
<url>
<loc>{{ page.url | replace:'/index.html','/' | absolute_url | xml_escape }}</loc>
<loc>{{ page.url | replace:'/index.html','/' | absolute_url | xml_escape | replace:'.html','' }}</loc>
</url>
{% endfor %}
</urlset>
2 changes: 1 addition & 1 deletion ios/NewExpensify/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>1.4.63.7</string>
<string>1.4.63.21</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSApplicationQueriesSchemes</key>
Expand Down
2 changes: 1 addition & 1 deletion ios/NewExpensifyTests/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.4.63.7</string>
<string>1.4.63.21</string>
</dict>
</plist>
2 changes: 1 addition & 1 deletion ios/NotificationServiceExtension/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<key>CFBundleShortVersionString</key>
<string>1.4.63</string>
<key>CFBundleVersion</key>
<string>1.4.63.7</string>
<string>1.4.63.21</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
Expand Down
Loading

0 comments on commit 051673b

Please sign in to comment.