Skip to content

Commit

Permalink
Merge branch 'main' into srikar-moveAllHeaderItemsToOverflow
Browse files Browse the repository at this point in the history
  • Loading branch information
srikarparsi authored Sep 28, 2023
2 parents 51a4a32 + 109e96c commit 289411f
Show file tree
Hide file tree
Showing 22 changed files with 283 additions and 244 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
title: Tax
description: How to track expense taxes
---
# Overview
Expensify’s tax tracking feature allows you to:
- Add tax names, rates, and codes whether you’re connected to an accounting system or not.
- Enable/disable taxes you’d like to make available to users.
- Set a default tax for Workspace currency expenses and, optionally, another default tax (including exempt) for foreign currency expenses which - will automatically apply to all new expenses.

# How to Enable Tax Tracking
Tax tracking can be enabled in the Tax section of the Workspace settings of any Workspace, whether group or individual.
## If Connected to an Accounting Integration
If your group Workspace is connected to Xero, QuickBooks Online, Sage Intacct, or NetSuite, make sure to first enable tax via the connection configuration page (Settings > Policies > Group > [Workspace Name] > Connections > Configure) and then sync the connection. Your tax rates will be imported from the accounting system and indicated by its logo.
## Not Connected to an Accounting Integration
If your Workspace is not connected to an accounting system, go to Settings > Policies > Group > [Workspace Name] > Tax to enable tax.

# Tracking Tax by Expense Category
To set a different tax rate for a specific expense type in the Workspace currency, go to Settings > Workspaces > Group > [Workspace Name] > Categories page. Click "Edit Rules" next to the desired category and set the "Category default tax". This will be applied to new expenses, overriding the default Workspace currency tax rate.
10 changes: 10 additions & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,16 @@ export default {
SETTINGS_PERSONAL_DETAILS_LEGAL_NAME: 'settings/profile/personal-details/legal-name',
SETTINGS_PERSONAL_DETAILS_DATE_OF_BIRTH: 'settings/profile/personal-details/date-of-birth',
SETTINGS_PERSONAL_DETAILS_ADDRESS: 'settings/profile/personal-details/address',
SETTINGS_PERSONAL_DETAILS_ADDRESS_COUNTRY: {
route: 'settings/profile/personal-details/address/country',
getRoute: (country: string, backTo?: string) => {
let route = `settings/profile/personal-details/address/country?country=${country}`;
if (backTo) {
route += `&backTo=${encodeURIComponent(backTo)}`;
}
return route;
},
},
SETTINGS_CONTACT_METHODS: 'settings/profile/contact-methods',
SETTINGS_CONTACT_METHOD_DETAILS: {
route: 'settings/profile/contact-methods/:contactMethod/details',
Expand Down
105 changes: 0 additions & 105 deletions src/components/CountryPicker/CountrySelectorModal.js

This file was deleted.

90 changes: 0 additions & 90 deletions src/components/CountryPicker/index.js

This file was deleted.

77 changes: 77 additions & 0 deletions src/components/CountrySelector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import React, {useEffect} from 'react';
import PropTypes from 'prop-types';
import {View} from 'react-native';
import styles from '../styles/styles';
import Navigation from '../libs/Navigation/Navigation';
import ROUTES from '../ROUTES';
import useLocalize from '../hooks/useLocalize';
import MenuItemWithTopDescription from './MenuItemWithTopDescription';
import FormHelpMessage from './FormHelpMessage';

const propTypes = {
/** Form error text. e.g when no country is selected */
errorText: PropTypes.string,

/** Callback called when the country changes. */
onInputChange: PropTypes.func.isRequired,

/** Current selected country */
value: PropTypes.string,

/** inputID used by the Form component */
// eslint-disable-next-line react/no-unused-prop-types
inputID: PropTypes.string.isRequired,

/** React ref being forwarded to the MenuItemWithTopDescription */
forwardedRef: PropTypes.func,
};

const defaultProps = {
errorText: '',
value: undefined,
forwardedRef: () => {},
};

function CountrySelector({errorText, value: countryCode, onInputChange, forwardedRef}) {
const {translate} = useLocalize();

const title = countryCode ? translate(`allCountries.${countryCode}`) : '';
const countryTitleDescStyle = title.length === 0 ? styles.textNormal : null;

useEffect(() => {
// This will cause the form to revalidate and remove any error related to country name
onInputChange(countryCode);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [countryCode]);

return (
<View>
<MenuItemWithTopDescription
shouldShowRightIcon
title={title}
ref={forwardedRef}
descriptionTextStyle={countryTitleDescStyle}
description={translate('common.country')}
onPress={() => {
const activeRoute = Navigation.getActiveRoute().replace(/\?.*/, '');
Navigation.navigate(ROUTES.SETTINGS_PERSONAL_DETAILS_ADDRESS_COUNTRY.getRoute(countryCode, activeRoute));
}}
/>
<View style={styles.ml5}>
<FormHelpMessage message={errorText} />
</View>
</View>
);
}

CountrySelector.propTypes = propTypes;
CountrySelector.defaultProps = defaultProps;
CountrySelector.displayName = 'CountrySelector';

export default React.forwardRef((props, ref) => (
<CountrySelector
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
forwardedRef={ref}
/>
));
2 changes: 1 addition & 1 deletion src/components/OptionRow.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ class OptionRow extends Component {
accessibilityRole={CONST.ACCESSIBILITY_ROLE.BUTTON}
hoverDimmingValue={1}
hoverStyle={this.props.hoverStyle}
needsOffscreenAlphaCompositing={this.props.option.icons.length >= 2}
needsOffscreenAlphaCompositing={lodashGet(this.props.option, 'icons.length', 0) >= 2}
>
<View style={sidebarInnerRowStyle}>
<View style={[styles.flexRow, styles.alignItemsCenter]}>
Expand Down
7 changes: 6 additions & 1 deletion src/components/ReportActionItem/MoneyRequestPreview.js
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,12 @@ function MoneyRequestPreview(props) {
errorRowStyles={[styles.mbn1]}
needsOffscreenAlphaCompositing
>
<View style={[isScanning || props.isWhisper ? styles.reportPreviewBoxHoverBorder : undefined]}>
<View
style={[
isScanning || props.isWhisper ? [styles.reportPreviewBoxHoverBorder, styles.reportContainerBorderRadius] : undefined,
!props.onPreviewPressed ? [styles.moneyRequestPreviewBox, ...props.containerStyles] : {},
]}
>
{hasReceipt && (
<ReportActionItemImages
images={receiptImages}
Expand Down
4 changes: 2 additions & 2 deletions src/components/ReportActionItem/TaskPreview.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ function TaskPreview(props) {
disabled={ReportUtils.isCanceledTaskReport(props.taskReport)}
onPress={Session.checkIfActionIsAllowed(() => {
if (isTaskCompleted) {
Task.reopenTask(props.taskReport, taskTitle);
Task.reopenTask(props.taskReport);
} else {
Task.completeTask(props.taskReport, taskTitle);
Task.completeTask(props.taskReport);
}
})}
accessibilityLabel={props.translate('task.task')}
Expand Down
4 changes: 2 additions & 2 deletions src/components/ReportActionItem/TaskView.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ function TaskView(props) {
<Checkbox
onPress={Session.checkIfActionIsAllowed(() => {
if (isCompleted) {
Task.reopenTask(props.report, taskTitle);
Task.reopenTask(props.report);
} else {
Task.completeTask(props.report, taskTitle);
Task.completeTask(props.report);
}
})}
isChecked={isCompleted}
Expand Down
6 changes: 2 additions & 4 deletions src/components/TaskHeaderActionButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,8 @@ function TaskHeaderActionButton(props) {
success
isDisabled={ReportUtils.isCanceledTaskReport(props.report) || !Task.canModifyTask(props.report, props.session.accountID)}
medium
text={props.translate(ReportUtils.isCompletedTaskReport(props.report) ? 'task.markAsIncomplete' : 'task.markAsDone')}
onPress={() =>
ReportUtils.isCompletedTaskReport(props.report) ? Task.reopenTask(props.report, props.report.reportName) : Task.completeTask(props.report, props.report.reportName)
}
text={props.translate(ReportUtils.isCompletedTaskReport(props.report) ? 'task.markAsIncomplete' : 'task.markAsComplete')}
onPress={() => (ReportUtils.isCompletedTaskReport(props.report) ? Task.reopenTask(props.report) : Task.completeTask(props.report))}
style={[styles.flex1]}
/>
</View>
Expand Down
6 changes: 3 additions & 3 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1535,12 +1535,12 @@ export default {
assignee: 'Assignee',
completed: 'Completed',
messages: {
completed: 'completed task',
completed: 'marked as complete',
canceled: 'deleted task',
reopened: 'reopened task',
reopened: 'marked as incomplete',
error: 'You do not have the permission to do the requested action.',
},
markAsDone: 'Mark as done',
markAsComplete: 'Mark as complete',
markAsIncomplete: 'Mark as incomplete',
assigneeError: 'There was an error assigning this task, please try another assignee.',
},
Expand Down
Loading

0 comments on commit 289411f

Please sign in to comment.