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

Accept receipt in request money #23770

Merged
merged 20 commits into from
Aug 3, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
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
3 changes: 3 additions & 0 deletions src/CONST.js
Original file line number Diff line number Diff line change
Expand Up @@ -1061,6 +1061,9 @@ const CONST = {
DELETE: 'delete',
},
AMOUNT_MAX_LENGTH: 10,
RECEIPT_STATE: {
SCANREADY: 'SCANREADY',
},
FILE_TYPES: {
HTML: 'html',
DOC: 'doc',
Expand Down
16 changes: 15 additions & 1 deletion src/libs/ReportUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -1762,9 +1762,22 @@ function getIOUReportActionMessage(type, total, comment, currency, paymentType =
* @param {String} [iouReportID] - Only required if the IOUReportActions type is oneOf(decline, cancel, pay). Generates a randomID as default.
* @param {Boolean} [isSettlingUp] - Whether we are settling up an IOU.
* @param {Boolean} [isSendMoneyFlow] - Whether this is send money flow
* @param {Object} [receipt]
* @returns {Object}
*/
function buildOptimisticIOUReportAction(type, amount, currency, comment, participants, transactionID, paymentType = '', iouReportID = '', isSettlingUp = false, isSendMoneyFlow = false) {
function buildOptimisticIOUReportAction(
type,
amount,
currency,
comment,
participants,
transactionID,
paymentType = '',
iouReportID = '',
isSettlingUp = false,
isSendMoneyFlow = false,
receipt = {},
) {
const IOUReportID = iouReportID || generateReportID();

const originalMessage = {
Expand Down Expand Up @@ -1810,6 +1823,7 @@ function buildOptimisticIOUReportAction(type, amount, currency, comment, partici
shouldShow: true,
created: DateUtils.getDBTime(),
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
receipt,
};
}

Expand Down
4 changes: 3 additions & 1 deletion src/libs/TransactionUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ import * as NumberUtils from './NumberUtils';
* @param {String} [source]
* @param {String} [originalTransactionID]
* @param {String} [merchant]
* @param {Object} [receipt]
* @returns {Object}
*/
function buildOptimisticTransaction(amount, currency, reportID, comment = '', source = '', originalTransactionID = '', merchant = CONST.REPORT.TYPE.IOU) {
function buildOptimisticTransaction(amount, currency, reportID, comment = '', source = '', originalTransactionID = '', merchant = CONST.REPORT.TYPE.IOU, receipt = {}) {
// transactionIDs are random, positive, 64-bit numeric strings.
// Because JS can only handle 53-bit numbers, transactionIDs are strings in the front-end (just like reportActionID)
const transactionID = NumberUtils.rand64();
Expand All @@ -36,6 +37,7 @@ function buildOptimisticTransaction(amount, currency, reportID, comment = '', so
merchant,
created: DateUtils.getDBTime(),
pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
receipt,
};
}

Expand Down
15 changes: 12 additions & 3 deletions src/libs/actions/IOU.js
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,10 @@ function buildOnyxDataForMoneyRequest(
* @param {Number} payeeAccountID
* @param {Object} participant
* @param {String} comment
* @param {Object} [receipt]
*
*/
function requestMoney(report, amount, currency, payeeEmail, payeeAccountID, participant, comment) {
function requestMoney(report, amount, currency, payeeEmail, payeeAccountID, participant, comment, receipt = undefined) {
luacmartins marked this conversation as resolved.
Show resolved Hide resolved
const payerEmail = OptionsListUtils.addSMSDomainIfPhoneNumber(participant.login);
const payerAccountID = Number(participant.accountID);
const isPolicyExpenseChat = participant.isPolicyExpenseChat;
Expand Down Expand Up @@ -343,8 +345,13 @@ function requestMoney(report, amount, currency, payeeEmail, payeeAccountID, part
: ReportUtils.buildOptimisticIOUReport(payeeAccountID, payerAccountID, amount, chatReport.reportID, currency);
}

// STEP 3: Build optimistic transaction
const optimisticTransaction = TransactionUtils.buildOptimisticTransaction(amount, currency, iouReport.reportID, comment);
// STEP 3: Build optimistic receipt and transaction
const receiptObject = {};
if (receipt && receipt.source) {
receiptObject.source = receipt.source;
receiptObject.state = CONST.IOU.RECEIPT_STATE.SCANREADY;
}
const optimisticTransaction = TransactionUtils.buildOptimisticTransaction(amount, currency, iouReport.reportID, comment, '', '', undefined, receiptObject);

// STEP 4: Build optimistic reportActions. We need:
// 1. CREATED action for the chatReport
Expand All @@ -363,6 +370,7 @@ function requestMoney(report, amount, currency, payeeEmail, payeeAccountID, part
optimisticTransaction.transactionID,
'',
iouReport.reportID,
receiptObject,
);

// Add optimistic personal details for participant
Expand Down Expand Up @@ -413,6 +421,7 @@ function requestMoney(report, amount, currency, payeeEmail, payeeAccountID, part
createdChatReportActionID: isNewChatReport ? optimisticCreatedActionForChat.reportActionID : 0,
createdIOUReportActionID: isNewIOUReport ? optimisticCreatedActionForIOU.reportActionID : 0,
reportPreviewReportActionID: reportPreviewAction.reportActionID,
receipt,
},
{optimisticData, successData, failureData},
);
Expand Down
33 changes: 32 additions & 1 deletion src/libs/fileDownload/FileUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,35 @@ function appendTimeToFileName(fileName) {
return newFileName;
}

export {showGeneralErrorAlert, showSuccessAlert, showPermissionErrorAlert, splitExtensionFromFileName, getAttachmentName, getFileType, cleanFileName, appendTimeToFileName};
/**
* Reads a locally uploaded file
*
* @param {String} path - the blob url of the locally uplodaded file
* @param {String} fileName
* @returns {Promise}
*/
const readFileAsync = (path, fileName) =>
new Promise((resolve) => {
if (!path) {
resolve();
}

return fetch(path)
.then((res) => {
if (!res.ok) {
throw Error(res.statusText);
}
return res.blob();
})
.then((blob) => {
const file = new File([blob], cleanFileName(fileName));
Copy link
Contributor

@s77rt s77rt Oct 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This caused a bug #26940. On Android the File API constructor needs the type to be specified otherwise network uploads would fail.

file.source = path;
resolve(file);
})
.catch((e) => {
console.debug('[FileUtils] Could not read uploaded file', e);
resolve();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are resolving even on failures? Shouldn't we reject?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We resolve with an undefined receipt file and the call to RequestMoney proceeds without the receipt.

I agree that we should eventually reject and display some error to the user, but I didn't see anything about it in the doc. Since this PR is blocking others in this project and we currently don't display errors in MoneyRequestConfirmPage, I think we should keep the scope of this PR smaller and tackle displaying an error as a follow up once we align on what error will be displayed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. Fine by me then.

});
});

export {showGeneralErrorAlert, showSuccessAlert, showPermissionErrorAlert, splitExtensionFromFileName, getAttachmentName, getFileType, cleanFileName, appendTimeToFileName, readFileAsync};
33 changes: 23 additions & 10 deletions src/pages/iou/steps/MoneyRequestConfirmPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import ONYXKEYS from '../../../ONYXKEYS';
import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from '../../../components/withCurrentUserPersonalDetails';
import reportPropTypes from '../../reportPropTypes';
import personalDetailsPropType from '../../personalDetailsPropType';
import * as FileUtils from '../../../libs/fileDownload/FileUtils';

const propTypes = {
report: reportPropTypes,
Expand Down Expand Up @@ -141,17 +142,29 @@ function MoneyRequestConfirmPage(props) {
return;
}

IOU.requestMoney(
props.report,
props.iou.amount,
props.iou.currency,
props.currentUserPersonalDetails.login,
props.currentUserPersonalDetails.accountID,
selectedParticipants[0],
trimmedComment,
);
FileUtils.readFileAsync(props.iou.receiptPath, props.iou.receiptSource).then((receipt) => {
luacmartins marked this conversation as resolved.
Show resolved Hide resolved
IOU.requestMoney(
props.report,
props.iou.amount,
props.iou.currency,
props.currentUserPersonalDetails.login,
props.currentUserPersonalDetails.accountID,
selectedParticipants[0],
trimmedComment,
receipt,
);
});
},
[props.iou.amount, props.iou.comment, props.currentUserPersonalDetails.login, props.currentUserPersonalDetails.accountID, props.iou.currency, props.report],
[
props.iou.amount,
props.iou.comment,
props.currentUserPersonalDetails.login,
props.currentUserPersonalDetails.accountID,
props.iou.currency,
props.report,
props.iou.receiptPath,
props.iou.receiptSource,
],
);

/**
Expand Down
Loading