Skip to content

Commit

Permalink
Merge pull request #23770 from Expensify/cmartins-requestMoneyReceipt
Browse files Browse the repository at this point in the history
Accept receipt in request money
  • Loading branch information
luacmartins authored Aug 3, 2023
2 parents 31b051a + 68afecf commit f3ece51
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 16 deletions.
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 @@ -310,8 +310,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) {
const payerEmail = OptionsListUtils.addSMSDomainIfPhoneNumber(participant.login);
const payerAccountID = Number(participant.accountID);
const isPolicyExpenseChat = participant.isPolicyExpenseChat;
Expand Down Expand Up @@ -355,8 +357,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 @@ -375,6 +382,7 @@ function requestMoney(report, amount, currency, payeeEmail, payeeAccountID, part
optimisticTransaction.transactionID,
'',
iouReport.reportID,
receiptObject,
);

// Add optimistic personal details for participant
Expand Down Expand Up @@ -425,6 +433,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));
file.source = path;
resolve(file);
})
.catch((e) => {
console.debug('[FileUtils] Could not read uploaded file', e);
resolve();
});
});

export {showGeneralErrorAlert, showSuccessAlert, showPermissionErrorAlert, splitExtensionFromFileName, getAttachmentName, getFileType, cleanFileName, appendTimeToFileName, readFileAsync};
50 changes: 40 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 @@ -109,6 +110,27 @@ function MoneyRequestConfirmPage(props) {
Navigation.goBack(fallback);
};

/**
* @param {Array} selectedParticipants
* @param {String} trimmedComment
* @param {File} [receipt]
*/
const requestMoney = useCallback(
(selectedParticipants, trimmedComment, receipt) => {
IOU.requestMoney(
props.report,
props.iou.amount,
props.iou.currency,
props.currentUserPersonalDetails.login,
props.currentUserPersonalDetails.accountID,
selectedParticipants[0],
trimmedComment,
receipt,
);
},
[props.report, props.iou.amount, props.iou.currency, props.currentUserPersonalDetails.login, props.currentUserPersonalDetails.accountID],
);

const createTransaction = useCallback(
(selectedParticipants) => {
const trimmedComment = props.iou.comment.trim();
Expand Down Expand Up @@ -141,17 +163,25 @@ function MoneyRequestConfirmPage(props) {
return;
}

IOU.requestMoney(
props.report,
props.iou.amount,
props.iou.currency,
props.currentUserPersonalDetails.login,
props.currentUserPersonalDetails.accountID,
selectedParticipants[0],
trimmedComment,
);
if (props.iou.receiptPath && props.iou.receiptSource) {
FileUtils.readFileAsync(props.iou.receiptPath, props.iou.receiptSource).then((receipt) => {
requestMoney(selectedParticipants, trimmedComment, receipt);
});
return;
}

requestMoney(selectedParticipants, trimmedComment);
},
[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.iou.receiptPath,
props.iou.receiptSource,
requestMoney,
],
);

/**
Expand Down

0 comments on commit f3ece51

Please sign in to comment.