Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
rayane-djouah committed Sep 9, 2024
2 parents f14a4e4 + 5bef7f5 commit 438130d
Show file tree
Hide file tree
Showing 19 changed files with 107 additions and 82 deletions.
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 1009003101
versionName "9.0.31-1"
versionCode 1009003103
versionName "9.0.31-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
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
title: Get Reimbursed Faster as a Non-US Employee
description: How to use Wise to get paid faster
---

If you are an overseas employee who works for a US-based company, you can use Wise to be reimbursed for expenses just as quickly as your US-based colleagues. Wise (formerly TransferWise) is an FCA-regulated global money transfer service.

Here’s how it works:

1. When you sign up for a Wise account, you are provided with a USD checking account number and a routing number to use as your Expensify bank account.
2. Once you receive a reimbursement, it will be deposited directly into your Wise account.
3. You can then convert your funds into 40+ different currencies and withdraw them to your local bank account. If you live in the UK or EU, you can also get a debit card to spend money directly from your Wise account.

## Set up reimbursements through Wise

1. Check with your company to see if you can submit your expenses in USD.
2. Sign up for a Wise Borderless Account and get verified (verification can take up to 3 days).
3. In Expensify, [add a deposit-only bank account](https://help.expensify.com/articles/expensify-classic/bank-accounts-and-payments/bank-accounts/Connect-Personal-US-Bank-Account) with your Wise USD account and ACH routing numbers (NOT the wire transfer routing number).

{% include info.html %}
Do not include spaces in the Wise account number, which should be 16 digits.
{% include end-info.html %}

If your expenses are not in USD, Expensify will automatically convert them to USD when they are added to your expense report. Once you submit your expenses to your company’s USD workspace and they are approved, you will receive the reimbursement for the approved report total in USD in your Wise account.
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>9.0.31.1</string>
<string>9.0.31.3</string>
<key>FullStory</key>
<dict>
<key>OrgId</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>9.0.31.1</string>
<string>9.0.31.3</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>9.0.31</string>
<key>CFBundleVersion</key>
<string>9.0.31.1</string>
<string>9.0.31.3</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
Expand Down
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
"version": "9.0.31-1",
"version": "9.0.31-3",
"author": "Expensify, Inc.",
"homepage": "https://new.expensify.com",
"description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",
Expand Down Expand Up @@ -113,7 +113,7 @@
"date-fns-tz": "^2.0.0",
"dom-serializer": "^0.2.2",
"domhandler": "^4.3.0",
"expensify-common": "2.0.83",
"expensify-common": "2.0.84",
"expo": "51.0.17",
"expo-av": "14.0.6",
"expo-image": "1.12.12",
Expand Down
12 changes: 2 additions & 10 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -550,16 +550,6 @@ export default {
sendAttachment: 'Send attachment',
addAttachment: 'Add attachment',
writeSomething: 'Write something...',
conciergePlaceholderOptions: [
'Ask for help!',
'Ask me anything!',
'Ask me to book travel!',
'Ask me what I can do!',
'Ask me how to pay people!',
'Ask me how to send an invoice!',
'Ask me how to scan a receipt!',
'Ask me how to get a free corporate card!',
],
blockedFromConcierge: 'Communication is barred',
fileUploadFailed: 'Upload failed. File is not supported.',
localTime: ({user, time}: LocalTimeParams) => `It's ${time} for ${user}`,
Expand Down Expand Up @@ -3573,6 +3563,8 @@ export default {
continueWithSetup: 'Continue with setup',
youreAlmostDone: "You're almost done setting up your bank account, which will let you issue corporate cards, reimburse expenses, collect invoices, and pay bills.",
streamlinePayments: 'Streamline payments',
connectBankAccountNote: "Note: Personal bank accounts can't be used for payments on workspaces.",
oneMoreThing: 'One more thing!',
allSet: "You're all set!",
accountDescriptionWithCards: 'This bank account will be used to issue corporate cards, reimburse expenses, collect invoices, and pay bills.',
letsFinishInChat: "Let's finish in chat!",
Expand Down
12 changes: 2 additions & 10 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -541,16 +541,6 @@ export default {
sendAttachment: 'Enviar adjunto',
addAttachment: 'Añadir archivo adjunto',
writeSomething: 'Escribe algo...',
conciergePlaceholderOptions: [
'¡Pide ayuda!',
'¡Pregúntame lo que sea!',
'¡Pídeme que te reserve un viaje!',
'¡Pregúntame qué puedo hacer!',
'¡Pregúntame cómo pagar a la gente!',
'¡Pregúntame cómo enviar una factura!',
'¡Pregúntame cómo escanear un recibo!',
'¡Pregúntame cómo obtener una tarjeta de crédito corporativa gratis!',
],
blockedFromConcierge: 'Comunicación no permitida',
fileUploadFailed: 'Subida fallida. El archivo no es compatible.',
localTime: ({user, time}: LocalTimeParams) => `Son las ${time} para ${user}`,
Expand Down Expand Up @@ -3621,6 +3611,8 @@ export default {
continueWithSetup: 'Continuar con la configuración',
youreAlmostDone: 'Casi has acabado de configurar tu cuenta bancaria, que te permitirá emitir tarjetas corporativas, reembolsar gastos y cobrar pagar facturas.',
streamlinePayments: 'Optimiza pagos',
connectBankAccountNote: 'Nota: No se pueden usar cuentas bancarias personales para realizar pagos en los espacios de trabajo.',
oneMoreThing: '¡Una cosa más!',
allSet: '¡Todo listo!',
accountDescriptionWithCards: 'Esta cuenta bancaria se utilizará para emitir tarjetas corporativas, reembolsar gastos y cobrar y pagar facturas.',
letsFinishInChat: '¡Continuemos en el chat!',
Expand Down
6 changes: 4 additions & 2 deletions src/libs/DistanceRequestUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type MileageRate = {
currency?: string;
unit: Unit;
name?: string;
enabled?: boolean;
};

let lastSelectedDistanceRates: OnyxEntry<LastSelectedDistanceRates> = {};
Expand All @@ -32,7 +33,7 @@ Onyx.connect({
const METERS_TO_KM = 0.001; // 1 kilometer is 1000 meters
const METERS_TO_MILES = 0.000621371; // There are approximately 0.000621371 miles in a meter

function getMileageRates(policy: OnyxInputOrEntry<Policy>, includeDisabledRates = false): Record<string, MileageRate> {
function getMileageRates(policy: OnyxInputOrEntry<Policy>, includeDisabledRates = false, selectedRateID?: string): Record<string, MileageRate> {
const mileageRates: Record<string, MileageRate> = {};

if (!policy?.customUnits) {
Expand All @@ -45,7 +46,7 @@ function getMileageRates(policy: OnyxInputOrEntry<Policy>, includeDisabledRates
}

Object.entries(distanceUnit.rates).forEach(([rateID, rate]) => {
if (!includeDisabledRates && rate.enabled === false) {
if (!includeDisabledRates && rate.enabled === false && (!selectedRateID || rateID !== selectedRateID)) {
return;
}

Expand All @@ -55,6 +56,7 @@ function getMileageRates(policy: OnyxInputOrEntry<Policy>, includeDisabledRates
unit: distanceUnit.attributes.unit,
name: rate.name,
customUnitRateID: rate.customUnitRateID,
enabled: rate.enabled,
};
});

Expand Down
2 changes: 1 addition & 1 deletion src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5878,7 +5878,7 @@ function doesTransactionThreadHaveViolations(
return (
TransactionUtils.hasViolation(IOUTransactionID, transactionViolations) ||
TransactionUtils.hasWarningTypeViolation(IOUTransactionID, transactionViolations) ||
TransactionUtils.hasModifiedAmountOrDateViolation(IOUTransactionID, transactionViolations)
(isPaidGroupPolicy(report) && TransactionUtils.hasModifiedAmountOrDateViolation(IOUTransactionID, transactionViolations))
);
}

Expand Down
71 changes: 47 additions & 24 deletions src/pages/ReimbursementAccount/BankAccountStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ import React from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import Button from '@components/Button';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import Icon from '@components/Icon';
import * as Expensicons from '@components/Icon/Expensicons';
import * as Illustrations from '@components/Icon/Illustrations';
import LottieAnimations from '@components/LottieAnimations';
import MenuItem from '@components/MenuItem';
import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback';
import ScreenWrapper from '@components/ScreenWrapper';
Expand Down Expand Up @@ -36,6 +35,9 @@ type BankAccountStepOnyxProps = {

/** If the plaid button has been disabled */
isPlaidDisabled: OnyxEntry<boolean>;

/** List of bank accounts */
bankAccountList: OnyxEntry<OnyxTypes.BankAccountList>;
};

type BankAccountStepProps = BankAccountStepOnyxProps & {
Expand Down Expand Up @@ -69,6 +71,7 @@ function BankAccountStep({
reimbursementAccount,
onBackButtonPress,
isPlaidDisabled = false,
bankAccountList = {},
}: BankAccountStepProps) {
const theme = useTheme();
const styles = useThemeStyles();
Expand All @@ -80,6 +83,7 @@ function BankAccountStep({
}
const plaidDesktopMessage = getPlaidDesktopMessage();
const bankAccountRoute = `${ROUTES.BANK_ACCOUNT_WITH_STEP_TO_OPEN.getRoute('new', policyID, ROUTES.WORKSPACE_INITIAL.getRoute(policyID))}`;
const personalBankAccounts = Object.keys(bankAccountList).filter((key) => bankAccountList[key].accountType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT);

const removeExistingBankAccountDetails = () => {
const bankAccountData: Partial<ReimbursementAccountForm> = {
Expand Down Expand Up @@ -119,34 +123,50 @@ function BankAccountStep({
/>
<ScrollView style={styles.flex1}>
<Section
icon={Illustrations.MoneyWings}
title={translate('workspace.bankAccount.streamlinePayments')}
illustration={LottieAnimations.FastMoney}
subtitle={translate('bankAccount.toGetStarted')}
subtitleMuted
illustrationBackgroundColor={theme.fallbackIconColor}
isCentralPane
>
<View style={styles.mv3}>
<Text>{translate('bankAccount.toGetStarted')}</Text>
</View>
{!!plaidDesktopMessage && (
<View style={[styles.mv3, styles.flexRow, styles.justifyContentBetween]}>
<View style={[styles.mt3, styles.flexRow, styles.justifyContentBetween]}>
<TextLink onPress={() => Link.openExternalLinkWithToken(bankAccountRoute)}>{translate(plaidDesktopMessage)}</TextLink>
</View>
)}
<Button
icon={Expensicons.Bank}
iconStyles={[styles.customMarginButtonWithMenuItem]}
text={translate('bankAccount.connectOnlineWithPlaid')}
onPress={() => {
if (!!isPlaidDisabled || !user?.validated) {
return;
}
removeExistingBankAccountDetails();
BankAccounts.openPlaidView();
}}
isDisabled={!!isPlaidDisabled || !user?.validated}
style={[styles.mt4]}
shouldShowRightIcon
success
innerStyles={[styles.pr2, styles.pl4, styles.h13]}
/>
{!!personalBankAccounts.length && (
<View style={[styles.flexRow, styles.mt4, styles.alignItemsCenter, styles.pb1, styles.pt1]}>
<Icon
src={Expensicons.Lightbulb}
fill={theme.icon}
additionalStyles={styles.mr2}
medium
/>
<Text
style={[styles.textLabelSupportingNormal, styles.flex1]}
suppressHighlighting
>
{translate('workspace.bankAccount.connectBankAccountNote')}
</Text>
</View>
)}
<View style={styles.mt3}>
<MenuItem
icon={Expensicons.Bank}
title={translate('bankAccount.connectOnlineWithPlaid')}
disabled={!!isPlaidDisabled || !user?.validated}
onPress={() => {
if (!!isPlaidDisabled || !user?.validated) {
return;
}
removeExistingBankAccountDetails();
BankAccounts.openPlaidView();
}}
shouldShowRightIcon
wrapperStyle={[styles.cardMenuItem]}
/>
</View>
<View style={styles.mv3}>
<MenuItem
icon={Expensicons.Connect}
Expand Down Expand Up @@ -195,4 +215,7 @@ export default withOnyx<BankAccountStepProps, BankAccountStepOnyxProps>({
isPlaidDisabled: {
key: ONYXKEYS.IS_PLAID_DISABLED,
},
bankAccountList: {
key: ONYXKEYS.BANK_ACCOUNT_LIST,
},
})(BankAccountStep);
4 changes: 2 additions & 2 deletions src/pages/home/ReportScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ function ReportScreen({route, currentReportID = '', navigation}: ReportScreenPro
const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {allowStaleData: true, initialValue: {}});
const [betas] = useOnyx(ONYXKEYS.BETAS);
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
const [parentReportAction] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportOnyx?.parentReportID || -1}`, {
const [parentReportAction] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportOnyx?.parentReportID || 0}`, {
canEvict: false,
selector: (parentReportActions) => getParentReportAction(parentReportActions, reportOnyx?.parentReportActionID ?? ''),
});
Expand All @@ -132,7 +132,7 @@ function ReportScreen({route, currentReportID = '', navigation}: ReportScreenPro
const isDeletedParentAction = ReportActionsUtils.isDeletedParentAction(parentReportAction);
const prevIsDeletedParentAction = usePrevious(isDeletedParentAction);

const isLoadingReportOnyx = !reportOnyx || Object.keys(reportOnyx).length === 0 || isLoadingOnyxValue(reportResult);
const isLoadingReportOnyx = isLoadingOnyxValue(reportResult);
const permissions = useDeepCompareRef(reportOnyx?.permissions);

useEffect(() => {
Expand Down
18 changes: 3 additions & 15 deletions src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -213,25 +213,13 @@ function ReportActionCompose({
const userBlockedFromConcierge = useMemo(() => User.isBlockedFromConcierge(blockedFromConcierge), [blockedFromConcierge]);
const isBlockedFromConcierge = useMemo(() => includesConcierge && userBlockedFromConcierge, [includesConcierge, userBlockedFromConcierge]);

// If we are on a small width device then don't show last 3 items from conciergePlaceholderOptions
const conciergePlaceholderRandomIndex = useMemo(
() => Math.floor(Math.random() * (translate('reportActionCompose.conciergePlaceholderOptions').length - (shouldUseNarrowLayout ? 4 : 1) + 1)),
// eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
[],
);

// Placeholder to display in the chat input.
const inputPlaceholder = useMemo(() => {
if (includesConcierge) {
if (userBlockedFromConcierge) {
return translate('reportActionCompose.blockedFromConcierge');
}

return translate('reportActionCompose.conciergePlaceholderOptions')[conciergePlaceholderRandomIndex];
if (includesConcierge && userBlockedFromConcierge) {
return translate('reportActionCompose.blockedFromConcierge');
}

return translate('reportActionCompose.writeSomething');
}, [includesConcierge, translate, userBlockedFromConcierge, conciergePlaceholderRandomIndex]);
}, [includesConcierge, translate, userBlockedFromConcierge]);

const focus = () => {
if (composerRef.current === null) {
Expand Down
2 changes: 1 addition & 1 deletion src/pages/home/report/ReportActionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ function ReportActionItem({
});
const theme = useTheme();
const styles = useThemeStyles();
const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID || -1}`);
const [reportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.reportID ?? -1}`);
const StyleUtils = useStyleUtils();
const personalDetails = usePersonalDetails() || CONST.EMPTY_OBJECT;
const [isContextMenuActive, setIsContextMenuActive] = useState(() => ReportActionContextMenu.isActiveReportAction(action.reportActionID));
Expand Down
Loading

0 comments on commit 438130d

Please sign in to comment.