Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimistically generate transactions in existing IOU flows #17718

Merged
merged 92 commits into from
May 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
c94e8f4
Create TransactionUtils.buildOptimisticTransaction
roryabraham Apr 20, 2023
5705e77
Oops, add export
roryabraham Apr 20, 2023
962009f
Make comment optional in buildOptimisticTransaction
roryabraham Apr 20, 2023
c2ab2fc
Setup transaction data w/ RBR in RequestMoney flow
roryabraham Apr 20, 2023
8d998d9
Make transactionID required in buildOptimisticIOUAction
roryabraham Apr 20, 2023
b68362d
Finish RequestMoney flow
roryabraham Apr 20, 2023
a6aec7f
Implement createSplitsAndOnyxData
roryabraham Apr 20, 2023
ae89202
Implement getPayMoneyRequestParams
roryabraham Apr 20, 2023
42ff9e4
Implement getSendMoneyParams
roryabraham Apr 20, 2023
d997104
Update JSDoc comment to make it clear iouTransactionID is not optional
roryabraham Apr 20, 2023
6d8d11d
Fix lint
roryabraham Apr 20, 2023
d85e4a0
Create PusherHelper abstraction
roryabraham Apr 20, 2023
c858075
Create test for requestMoney
roryabraham Apr 21, 2023
9176a17
Refactor fetch mock
roryabraham Apr 21, 2023
f622e5c
Create test for requestMoney with existing chatReport
roryabraham Apr 21, 2023
4b79c27
Create test for requestMoney with existing chatReport and iouReport
roryabraham Apr 21, 2023
619e5cb
Add test for failing scenario
roryabraham Apr 21, 2023
cb9ceed
Merge branch 'main' into Rory-OptimisticTransactions
roryabraham Apr 24, 2023
83b0bc7
Remove unused PusherHelper
roryabraham Apr 24, 2023
afda245
Update TODO link
roryabraham Apr 24, 2023
0fe4736
Merge branch 'main' into Rory-OptimisticTransactions
roryabraham Apr 24, 2023
3ee3eb8
Upgrade Onyx to 1.0.41
roryabraham Apr 24, 2023
0a1a59b
Remove resolved TODOS
roryabraham Apr 24, 2023
d7c84c6
Fix IOUUtilsTest
roryabraham Apr 24, 2023
99e89a2
Clarify comment on global fetch mock
roryabraham Apr 24, 2023
00fbb9b
Fix IOU split transaction amounts
roryabraham Apr 24, 2023
acbedf8
Add test for SplitBill
roryabraham Apr 24, 2023
12a27a9
Standardize on cents for transactions
roryabraham Apr 24, 2023
f745bf6
Add assertions for IOU type
roryabraham Apr 24, 2023
9511280
Add assertions for originalMessage.IOUReportID
roryabraham Apr 25, 2023
bc1cf76
Add reportID to transaction
roryabraham Apr 25, 2023
a264814
Update SplitBill test to account for group transaction
roryabraham Apr 25, 2023
ff72d4f
Add comment field to optimistic transactions
roryabraham Apr 25, 2023
f34a677
Add string formatting util
roryabraham Apr 25, 2023
bf1586f
Add merchant to transactions
roryabraham Apr 25, 2023
b9d960f
Merge branch 'main' into Rory-OptimisticTransactions
roryabraham May 1, 2023
6bd14d7
iouTransactionID -> transactionID
roryabraham May 1, 2023
c13d018
Update comment
roryabraham May 1, 2023
d2669e6
Fix lint
roryabraham May 1, 2023
c81c126
Fix missed lint items
roryabraham May 1, 2023
b9defaa
Remove unnecessary NumberUtils function
roryabraham May 1, 2023
d1dc16d
Rename ID_DELETED to SPLIT_REPORTID
roryabraham May 2, 2023
89a57c2
Fix JSDoc comment in buildOptimisticIOUReportAction
roryabraham May 2, 2023
4f346e2
Use StringUtils instead of one-off code
roryabraham May 2, 2023
55d3994
Fix typo
roryabraham May 2, 2023
bb22ec2
Merge branch 'main' into Rory-OptimisticTransactions
roryabraham May 2, 2023
114482d
Clarify jest comment
roryabraham May 2, 2023
2bedfa6
pendingAction not pendingFields
roryabraham May 2, 2023
d8db068
Fix comments in tests
roryabraham May 2, 2023
adb91e1
Fix amount / comment discrepancy
roryabraham May 2, 2023
0b5f90f
Move cleanup to another promise block
roryabraham May 2, 2023
b8181f1
Fix lint
roryabraham May 2, 2023
a06911f
Simplify initialization of IOUUtilsTest
roryabraham May 2, 2023
e935e01
Merge branch 'main' into Rory-OptimisticTransactions
roryabraham May 2, 2023
3cff94b
Correct comment
roryabraham May 2, 2023
5de881a
Internationalize string formatter
roryabraham May 3, 2023
382e802
Localize split bill merchant
roryabraham May 3, 2023
50105d9
Use SET for optimistic transactions
roryabraham May 3, 2023
d2d9ce3
Change CurrencySymbolUtils to just CurrencyUtils
roryabraham May 3, 2023
6ca0f60
Move some IOUUtils to CurrencyUtils
roryabraham May 3, 2023
9256a73
Create function to convert amount to smallest unit
roryabraham May 3, 2023
422e56d
Create convertToDisplayString function
roryabraham May 3, 2023
4e13073
Always use CurrencyUtils for the amount in the requestMoney flow
roryabraham May 3, 2023
9f14ad3
don't convert transaction amount
roryabraham May 3, 2023
53791cf
Always use smallest currency units for SplitBill flows
roryabraham May 3, 2023
164dd2b
Add convertToWholeUnits function
roryabraham May 3, 2023
a968d31
Standardize currency handling across the money request flow
roryabraham May 3, 2023
296e458
Use CurrencyUtils.convertToDisplayString everywhere
roryabraham May 3, 2023
1aba2a3
Refactor CurrencyUtils.convertToDisplayString with USD as default cur…
roryabraham May 3, 2023
6dc9879
Fix lint
roryabraham May 3, 2023
dd11c8f
Create getLinkedTransactionID function
roryabraham May 3, 2023
89ee785
Fix typo
roryabraham May 3, 2023
9900bb0
Fix IOU tests
roryabraham May 3, 2023
609797b
Fix IOUUtilsTest
roryabraham May 3, 2023
80339aa
Fix RBR for RequestMoney flow
roryabraham May 3, 2023
22c4c65
Standardize dismissal of reportAction errors and add test coverage
roryabraham May 3, 2023
9e86e64
Correctly implement DeleteReport
roryabraham May 3, 2023
92cbd4f
Correctly implement RBR for SplitBill and SendMoney
roryabraham May 3, 2023
75bffd3
Fix incorrect extra nesting of errors
roryabraham May 4, 2023
37b7aaa
Fix deleteReport and RBR for SplitBill
roryabraham May 4, 2023
a01c8b9
Remove accidentally committed code
roryabraham May 4, 2023
558c056
Merge branch 'main' into Rory-OptimisticTransactions
roryabraham May 4, 2023
af9c824
Update IntlPolyfill to include ListFormat
roryabraham May 4, 2023
e22b9db
Merge branch 'main' into Rory-OptimisticTransactions
roryabraham May 4, 2023
8a51895
Fix lint errors from bad merge
roryabraham May 4, 2023
28954e0
Fix IOUUtilsTest
roryabraham May 4, 2023
c03cb8b
Fix polyfill export
roryabraham May 4, 2023
e68b986
Fix Intl polyfill
roryabraham May 4, 2023
7a9fbbc
Remove debug logs
roryabraham May 4, 2023
74bef77
Fix lint
roryabraham May 4, 2023
78b59bd
Update src/libs/CurrencyUtils.js
roryabraham May 5, 2023
dbf456d
Update src/libs/CurrencyUtils.js
roryabraham May 5, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions jest/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ reanimatedJestUtils.setUpTests();
// https://reactnavigation.org/docs/testing/#mocking-native-modules
jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper');

// We have to mock the SQLiteStorage provider because it uses the native module SQLiteStorage, which is not available in jest.
// Mocking this file in __mocks__ does not work because jest doesn't support mocking files that are not directly used in the testing project
jest.mock('react-native-onyx/lib/storage/providers/SQLiteStorage', () => require('react-native-onyx/lib/storage/__mocks__'));
// Mock react-native-onyx storage layer because the SQLite storage layer doesn't work in jest.
// Mocking this file in __mocks__ does not work because jest doesn't support mocking files that are not directly used in the testing project,
// and we only want to mock the storage layer, not the whole Onyx module.
jest.mock('react-native-onyx/lib/storage', () => require('react-native-onyx/lib/storage/__mocks__'));

// Turn off the console logs for timing events. They are not relevant for unit tests and create a lot of noise
jest.spyOn(console, 'debug').mockImplementation((...params) => {
Expand Down
168 changes: 106 additions & 62 deletions package-lock.json

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

11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,11 @@
},
"dependencies": {
"@expensify/react-native-web": "0.18.15",
"@formatjs/intl-getcanonicallocales": "^1.5.8",
"@formatjs/intl-locale": "^2.4.21",
"@formatjs/intl-numberformat": "^6.2.5",
"@formatjs/intl-pluralrules": "^4.0.13",
"@formatjs/intl-getcanonicallocales": "^2.2.0",
"@formatjs/intl-listformat": "^7.2.2",
"@formatjs/intl-locale": "^3.3.0",
"@formatjs/intl-numberformat": "^8.5.0",
"@formatjs/intl-pluralrules": "^5.2.2",
"@gorhom/portal": "^1.0.14",
"@oguzhnatly/react-native-image-manipulator": "github:Expensify/react-native-image-manipulator#c5f654fc9d0ad7cc5b89d50b34ecf8b0e3f4d050",
"@onfido/react-native-sdk": "7.4.0",
Expand Down Expand Up @@ -109,7 +110,7 @@
"react-native-key-command": "^1.0.0",
"react-native-localize": "^2.2.6",
"react-native-modal": "^13.0.0",
"react-native-onyx": "^1.0.41",
"react-native-onyx": "1.0.41",
"react-native-pdf": "^6.6.2",
"react-native-performance": "^4.0.0",
"react-native-permissions": "^3.0.1",
Expand Down
1 change: 1 addition & 0 deletions src/CONST.js
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ const CONST = {
DROP_NATIVE_ID: 'report-dropzone',
ACTIVE_DROP_NATIVE_ID: 'report-dropzone',
MAXIMUM_PARTICIPANTS: 8,
SPLIT_REPORTID: '-2',
ACTIONS: {
LIMIT: 50,
TYPE: {
Expand Down
6 changes: 2 additions & 4 deletions src/components/CurrentWalletBalance.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import withLocalize, {withLocalizePropTypes} from './withLocalize';
import compose from '../libs/compose';
import ONYXKEYS from '../ONYXKEYS';
import Text from './Text';
import * as CurrencyUtils from '../libs/CurrencyUtils';

const propTypes = {
/** The user's wallet account */
Expand All @@ -31,10 +32,7 @@ const defaultProps = {
};

const CurrentWalletBalance = (props) => {
const formattedBalance = props.numberFormat(
props.userWallet.currentBalance / 100, // Divide by 100 because balance is in cents
{style: 'currency', currency: 'USD'},
);
const formattedBalance = CurrencyUtils.convertToDisplayString(props.userWallet.currentBalance);
return (
<Text
style={[styles.pv5, styles.alignSelfCenter, styles.textHeadline, styles.textXXXLarge, ...props.balanceStyles]}
Expand Down
34 changes: 11 additions & 23 deletions src/components/MoneyRequestConfirmationList.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import * as IOUUtils from '../libs/IOUUtils';
import MenuItemWithTopDescription from './MenuItemWithTopDescription';
import Navigation from '../libs/Navigation/Navigation';
import optionPropTypes from './optionPropTypes';
import * as CurrencyUtils from '../libs/CurrencyUtils';

const propTypes = {
/** Callback to inform parent modal of success */
Expand All @@ -31,7 +32,7 @@ const propTypes = {
hasMultipleParticipants: PropTypes.bool.isRequired,

/** IOU amount */
iouAmount: PropTypes.string.isRequired,
iouAmount: PropTypes.number.isRequired,

/** IOU type */
iouType: PropTypes.string,
Expand Down Expand Up @@ -104,12 +105,10 @@ class MoneyRequestConfirmationList extends Component {
*/
getSplitOrRequestOptions() {
return [{
text: this.props.translate(this.props.hasMultipleParticipants ? 'iou.split' : 'iou.request', {
amount: this.props.numberFormat(
this.props.iouAmount,
{style: 'currency', currency: this.props.iou.selectedCurrencyCode},
),
}),
text: this.props.translate(
this.props.hasMultipleParticipants ? 'iou.split' : 'iou.request',
{amount: CurrencyUtils.convertToDisplayString(this.props.iouAmount, this.props.iou.selectedCurrencyCode)},
),
value: this.props.hasMultipleParticipants ? CONST.IOU.MONEY_REQUEST_TYPE.SPLIT : CONST.IOU.MONEY_REQUEST_TYPE.REQUEST,
}];
}
Expand All @@ -136,14 +135,10 @@ class MoneyRequestConfirmationList extends Component {
* @returns {Array}
*/
getParticipantsWithAmount(participants) {
const iouAmount = IOUUtils.calculateAmount(participants, this.props.iouAmount, this.props.iou.selectedCurrencyCode);

const iouAmount = IOUUtils.calculateAmount(participants, this.props.iouAmount);
return OptionsListUtils.getIOUConfirmationOptionsFromParticipants(
participants,
this.props.numberFormat(iouAmount / 100, {
style: 'currency',
currency: this.props.iou.selectedCurrencyCode,
}),
CurrencyUtils.convertToDisplayString(iouAmount, this.props.iou.selectedCurrencyCode),
);
}

Expand Down Expand Up @@ -172,13 +167,10 @@ class MoneyRequestConfirmationList extends Component {
const formattedUnselectedParticipants = this.getParticipantsWithoutAmount(unselectedParticipants);
const formattedParticipants = _.union(formattedSelectedParticipants, formattedUnselectedParticipants);

const myIOUAmount = IOUUtils.calculateAmount(selectedParticipants, this.props.iouAmount, this.props.iou.selectedCurrencyCode, true);
const myIOUAmount = IOUUtils.calculateAmount(selectedParticipants, this.props.iouAmount, true);
const formattedMyPersonalDetails = OptionsListUtils.getIOUConfirmationOptionsFromMyPersonalDetail(
this.props.currentUserPersonalDetails,
this.props.numberFormat(myIOUAmount / 100, {
style: 'currency',
currency: this.props.iou.selectedCurrencyCode,
}),
CurrencyUtils.convertToDisplayString(myIOUAmount, this.props.iou.selectedCurrencyCode),
);

sections.push({
Expand Down Expand Up @@ -270,18 +262,14 @@ class MoneyRequestConfirmationList extends Component {
const shouldDisableButton = selectedParticipants.length === 0;
const recipient = this.state.participants[0];
const canModifyParticipants = this.props.canModifyParticipants && this.props.hasMultipleParticipants;
const formattedAmount = this.props.numberFormat(this.props.iouAmount, {
style: 'currency',
currency: this.props.iou.selectedCurrencyCode,
});
const formattedAmount = CurrencyUtils.convertToDisplayString(this.props.iouAmount, this.props.iou.selectedCurrencyCode);

return (
<OptionsSelector
sections={this.getSections()}
value=""
onSelectRow={canModifyParticipants ? this.toggleOption : undefined}
onConfirmSelection={this.confirm}
onChangeText={this.props.onUpdateComment}
selectedOptions={this.getSelectedOptions()}
canSelectMultipleOptions={canModifyParticipants}
disableArrowKeysActions={!canModifyParticipants}
Expand Down
Loading