diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d4a851edda6f..595152e18d45 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,10 +1,10 @@ - + ### Details - + ### Fixed Issues - + Fixes GH_LINK ### Tests diff --git a/package-lock.json b/package-lock.json index 6f889ed54a98..5e6988321e0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21813,19 +21813,19 @@ } }, "react-native-onyx": { - "version": "git+https://github.com/Expensify/react-native-onyx.git#3635fc34f00c8c8f97500b97fd42251ab4d22ab5", - "from": "git+https://github.com/Expensify/react-native-onyx.git#3635fc34f00c8c8f97500b97fd42251ab4d22ab5", + "version": "git+https://github.com/Expensify/react-native-onyx.git#accabbd24b5d9a4556b9619a47ba081325622c46", + "from": "git+https://github.com/Expensify/react-native-onyx.git#accabbd24b5d9a4556b9619a47ba081325622c46", "requires": { "@react-native-community/async-storage": "^1.12.1", - "expensify-common": "git+https://github.com/Expensify/expensify-common.git#3d8fc7500ddd24cd4a543e6e160d4f1ad97cc145", + "expensify-common": "git+https://github.com/Expensify/expensify-common.git#679fc86cfc4f9bc701e3757d583d74057edbbe28", "lodash": "4.17.21", "react": "^16.13.1", "underscore": "^1.11.0" }, "dependencies": { "expensify-common": { - "version": "git+https://github.com/Expensify/expensify-common.git#3d8fc7500ddd24cd4a543e6e160d4f1ad97cc145", - "from": "git+https://github.com/Expensify/expensify-common.git#3d8fc7500ddd24cd4a543e6e160d4f1ad97cc145", + "version": "git+https://github.com/Expensify/expensify-common.git#679fc86cfc4f9bc701e3757d583d74057edbbe28", + "from": "git+https://github.com/Expensify/expensify-common.git#679fc86cfc4f9bc701e3757d583d74057edbbe28", "requires": { "classnames": "2.2.5", "clipboard": "2.0.4", diff --git a/package.json b/package.json index 3dac506a1804..6d9196790e8a 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "react-native-image-picker": "^2.3.3", "react-native-keyboard-spacer": "^0.4.1", "react-native-modal": "^11.5.6", - "react-native-onyx": "git+https://github.com/Expensify/react-native-onyx.git#3635fc34f00c8c8f97500b97fd42251ab4d22ab5", + "react-native-onyx": "git+https://github.com/Expensify/react-native-onyx.git#accabbd24b5d9a4556b9619a47ba081325622c46", "react-native-pdf": "^6.2.2", "react-native-picker-select": "8.0.4", "react-native-reanimated": "1.13.2", diff --git a/src/components/IOUConfirmationList.js b/src/components/IOUConfirmationList.js index 8bcf8837736b..188e93b44bf6 100644 --- a/src/components/IOUConfirmationList.js +++ b/src/components/IOUConfirmationList.js @@ -104,7 +104,7 @@ class IOUConfirmationList extends Component { sections.push({ title: 'WHO PAID?', - data: formattedMyPersonalDetails, + data: [formattedMyPersonalDetails], shouldShow: true, indexOffset: 0, }); @@ -132,9 +132,15 @@ class IOUConfirmationList extends Component { /** * Gets splits for the transaction * - * @returns {Array} + * @returns {Array|null} */ getSplits() { + // There can only be splits when there are multiple participants, so return early when there are not + // multiple participants + if (!this.props.hasMultipleParticipants) { + return null; + } + const splits = this.props.participants.map(participant => ({ email: participant.login, @@ -169,8 +175,13 @@ class IOUConfirmationList extends Component { * @returns {Array} */ getAllOptionsAsSelected() { - return [...this.props.participants, - getIOUConfirmationOptionsFromMyPersonalDetail(this.props.myPersonalDetails)]; + if (!this.props.hasMultipleParticipants) { + return []; + } + return [ + ...this.props.participants, + getIOUConfirmationOptionsFromMyPersonalDetail(this.props.myPersonalDetails), + ]; } /** @@ -208,7 +219,7 @@ class IOUConfirmationList extends Component { forceTextUnreadStyle canSelectMultipleOptions={this.props.hasMultipleParticipants} disableFocusOptions - selectedOptions={this.props.hasMultipleParticipants && this.getAllOptionsAsSelected()} + selectedOptions={this.getAllOptionsAsSelected()} /> @@ -229,13 +240,7 @@ class IOUConfirmationList extends Component { { - if (this.props.hasMultipleParticipants) { - this.props.onConfirm({splits: this.getSplits()}); - } else { - this.props.onConfirm({}); - } - }} + onClick={() => this.props.onConfirm(this.getSplits())} /> diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index e9490f30c735..0c035c1c4f12 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -364,18 +364,15 @@ function getNewChatOptions( * * @param {Object} myPersonalDetail * @param {String} amountText - * @returns {Array} + * @returns {Object} */ -function getIOUConfirmationOptionsFromMyPersonalDetail( - myPersonalDetail, - amountText, -) { - return [{ +function getIOUConfirmationOptionsFromMyPersonalDetail(myPersonalDetail, amountText) { + return { text: myPersonalDetail.displayName, alternateText: myPersonalDetail.login, icons: [myPersonalDetail.avatar], descriptiveText: amountText, - }]; + }; } /** diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index f56871642da9..4915654ccc21 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -17,35 +17,44 @@ function getPreferredCurrency() { } /** - * @param {Array} reportIds + * @param {Object[]} requestParams + * @param {Number} requestParams.reportID the ID of the IOU report + * @param {Number} requestParams.chatReportID the ID of the chat report that the IOU report belongs to * @returns {Promise} * Gets the IOU Reports for new transaction */ -function getIOUReportsForNewTransaction(reportIds) { +function getIOUReportsForNewTransaction(requestParams) { return API.Get({ returnValueList: 'reportStuff', - reportIDList: reportIds, + reportIDList: _.pluck(requestParams, 'reportID'), shouldLoadOptionalKeys: true, includePinnedReports: true, }) - .then(({reports}) => _.map(reports, getSimplifiedIOUReport)) - .then((iouReportObjects) => { - const reportIOUData = {}; + .then(({reports}) => { + const chatReportsToUpdate = {}; + const iouReportsToUpdate = {}; - if (iouReportObjects.length === 1) { - const iouReportKey = `${ONYXKEYS.COLLECTION.REPORT_IOUS}${iouReportObjects[0].reportID}`; - return Onyx.merge(iouReportKey, - getSimplifiedIOUReport(iouReportObjects[0])); - } + _.each(reports, (reportData) => { + // First, the existing chat report needs updated with the details about the new IOU + const paramsForIOUReport = _.findWhere(requestParams, {reportID: reportData.reportID}); + if (paramsForIOUReport && paramsForIOUReport.chatReportID) { + const chatReportKey = `${ONYXKEYS.COLLECTION.REPORT}${paramsForIOUReport.chatReportID}`; + chatReportsToUpdate[chatReportKey] = { + iouReportID: reportData.reportID, + total: reportData.total, + stateNum: reportData.stateNum, + hasOutstandingIOU: true, + }; - _.each(iouReportObjects, (iouReportObject) => { - if (!iouReportObject) { - return; + // Second, the IOU report needs updated with the new IOU details too + const iouReportKey = `${ONYXKEYS.COLLECTION.REPORT_IOUS}${reportData.reportID}`; + iouReportsToUpdate[iouReportKey] = getSimplifiedIOUReport(reportData, reportData.reportID); } - const iouReportKey = `${ONYXKEYS.COLLECTION.REPORT_IOUS}${iouReportObject.reportID}`; - reportIOUData[iouReportKey] = iouReportObject; }); - return Onyx.mergeCollection(ONYXKEYS.COLLECTION.REPORT_IOUS, {...reportIOUData}); + + // Now, merge the updated objects into our store + Onyx.mergeCollection(ONYXKEYS.COLLECTION.REPORT, chatReportsToUpdate); + return Onyx.mergeCollection(ONYXKEYS.COLLECTION.REPORT_IOUS, iouReportsToUpdate); }) .catch(() => Onyx.merge(ONYXKEYS.IOU, {loading: false, creatingIOUTransaction: false, error: true})) .finally(() => Onyx.merge(ONYXKEYS.IOU, {loading: false, creatingIOUTransaction: false})); @@ -53,58 +62,53 @@ function getIOUReportsForNewTransaction(reportIds) { /** * Creates IOUSplit Transaction - * @param {Object} parameters - * @param {String} parameters.amount - * @param {String} parameters.comment - * @param {String} parameters.currency - * @param {String} parameters.debtorEmail + * @param {Object} params + * @param {String} params.amount + * @param {String} params.comment + * @param {String} params.currency + * @param {String} params.debtorEmail */ -function createIOUTransaction({ - comment, amount, currency, debtorEmail, -}) { +function createIOUTransaction(params) { Onyx.merge(ONYXKEYS.IOU, {loading: true, creatingIOUTransaction: true, error: false}); - API.CreateIOUTransaction({ - comment, - amount, - currency, - debtorEmail, - }) - .then(data => data.reportID) - .then(reportID => getIOUReportsForNewTransaction([reportID])); + API.CreateIOUTransaction(params) + .then(data => getIOUReportsForNewTransaction([data])); } /** * Creates IOUSplit Transaction - * @param {Object} parameters - * @param {Array} parameters.splits - * @param {String} parameters.comment - * @param {String} parameters.amount - * @param {String} parameters.currency + * @param {Object} params + * @param {Array} params.splits + * @param {String} params.comment + * @param {String} params.amount + * @param {String} params.currency */ -function createIOUSplit({ - comment, - amount, - currency, - splits, -}) { +function createIOUSplit(params) { Onyx.merge(ONYXKEYS.IOU, {loading: true, creatingIOUTransaction: true, error: false}); API.CreateChatReport({ - emailList: splits.map(participant => participant.email).join(','), + emailList: params.splits.map(participant => participant.email).join(','), }) - .then((data) => { - console.debug(data); - return data.reportID; - }) - .then(reportID => API.CreateIOUSplit({ - splits: JSON.stringify(splits), - currency, - amount, - comment, - reportID, + .then(data => API.CreateIOUSplit({ + ...params, + splits: JSON.stringify(params.splits), + reportID: data.reportID, })) - .then(data => data.reportIDList) - .then(reportIDList => getIOUReportsForNewTransaction(reportIDList)); + .then((data) => { + // This data needs to go from this: + // {reportIDList: [1, 2], chatReportIDList: [3, 4]} + // to this: + // [{reportID: 1, chatReportID: 3}, {reportID: 2, chatReportID: 4}] + // in order for getIOUReportsForNewTransaction to know which IOU reports are associated with which + // chat reports + const reportParams = []; + for (let i = 0; i < data.reportIDList.length; i++) { + reportParams.push({ + reportID: data.reportIDList[i], + chatReportID: data.chatReportIDList[i], + }); + } + getIOUReportsForNewTransaction(reportParams); + }); } export { diff --git a/src/libs/actions/Report.js b/src/libs/actions/Report.js index d4769920c343..4eb3d91c104a 100644 --- a/src/libs/actions/Report.js +++ b/src/libs/actions/Report.js @@ -177,7 +177,7 @@ function getSimplifiedReportObject(report) { * @param {String} reportData.ownerEmail * @param {String} reportData.managerEmail * @param {Number} reportData.reportID - * @param {Number} chatReportID + * @param {Number|String} chatReportID * @returns {Object} */ function getSimplifiedIOUReport(reportData, chatReportID) { @@ -195,12 +195,13 @@ function getSimplifiedIOUReport(reportData, chatReportID) { managerEmail: reportData.managerEmail, currency: reportData.currency, transactions, - chatReportID, + chatReportID: Number(chatReportID), state: reportData.state, cachedTotal: reportData.cachedTotal, total: reportData.total, status: reportData.status, stateNum: reportData.stateNum, + hasOutstandingIOU: reportData.stateNum === 1 && reportData.total !== 0, }; } diff --git a/src/pages/iou/IOUModal.js b/src/pages/iou/IOUModal.js index 269074eac1c6..f3fe5f198afc 100644 --- a/src/pages/iou/IOUModal.js +++ b/src/pages/iou/IOUModal.js @@ -180,9 +180,12 @@ class IOUModal extends Component { this.setState({selectedCurrency}); } - createTransaction({splits}) { + /** + * @param {Array} [splits] + */ + createTransaction(splits) { if (splits) { - return createIOUSplit({ + createIOUSplit({ comment: this.state.comment, // should send in cents to API @@ -190,18 +193,10 @@ class IOUModal extends Component { currency: this.state.selectedCurrency, splits, }); + return; } - console.debug({ - comment: this.state.comment, - - // should send in cents to API - amount: this.state.amount * 100, - currency: this.state.selectedCurrency, - debtorEmail: this.state.participants[0].login, - }); - - return createIOUTransaction({ + createIOUTransaction({ comment: this.state.comment, // should send in cents to API